diff --git a/README.md b/README.md index 32927f6a..5b85f232 100755 --- a/README.md +++ b/README.md @@ -125,7 +125,27 @@ server { - **路径自动适配**:本项目已重构 `config.js`,部署时会自动识别 Linux 路径,无需手动修改 `config.json`。 - **库文件全内置**:`arduino-libs` 已包含在 Git 仓库中,`git clone` 后即可直接编译带库的工程。 -## 6. 常见问题排查 +## 7. 日常维护与热更新 + +如果你在本地对代码进行了修改并不想重新执行全量部署,可以通过以下步骤快速同步: + +```bash +# 进入服务端目录 +cd mixly3-server + +# 1. 拉取最新代码 (包含核心逻辑修复或板卡库更新) +git pull + +# 2. 重新构建生产代码 (非常重要:只要有 src 目录的改动就必须执行) +npm run build:prod + +# 3. 重启服务 +# 如果你是用 npm start 运行的,先 Ctrl+C 中断再运行即可。 +# 如果你是用 pm2 管理的,执行: +pm2 reload mixly3 +``` + +## 8. 常见问题排查 - **HTTPS 访问**:默认运行在 `https://你的IP:7100`。 - **反向代理配置**:如果使用 Nginx 反代,请务必处理好的 WebSocket (Upgrade) 头,否则页面无法连接。 diff --git a/mixly/CHANGELOG.md b/mixly/CHANGELOG.md new file mode 100644 index 00000000..cb7c65e2 --- /dev/null +++ b/mixly/CHANGELOG.md @@ -0,0 +1,463 @@ +### 更新日志 + +#### 3.0 rc0 2024-08-25 + +- 修复 Arduino UNO和NANO的软件中断均无效,程序下载后测试无中断响应. [\#I8CLTQ](https://gitee.com/mixly2/mixly2.0_src/issues/I8CLTQ) +- 修复 Arduino UNO中调用红外发射功能,管脚号不正确. [\#I8EBUM](https://gitee.com/mixly2/mixly2.0_src/issues/I8EBUM) +- 修复 Python Robot中,超霸大师RFID错误. [\#I8JIUB](https://gitee.com/mixly2/mixly2.0_src/issues/I8JIUB) +- 修复 Python中的算法库有加载问题. [\#I8L6Z9](https://gitee.com/mixly2/mixly2.0_src/issues/I8L6Z9) +- 修复 Arduino ESP32C3中SD和SPIFFS说明相反. [\#I8MCAJ](https://gitee.com/mixly2/mixly2.0_src/issues/I8MCAJ) +- 修复 英文语言下Control-Delay模块时间单位缩写混沌. [\#I8MSB3](https://gitee.com/mixly2/mixly2.0_src/issues/I8MSB3) +- 修复 Arduino板卡下TFT屏-ST7796构建时出错. [\#I8QWPK](https://gitee.com/mixly2/mixly2.0_src/issues/I8QWPK) +- 修复 Arduino板卡下TFT屏中的显示文本有Bug. [\#I8ZQ24](https://gitee.com/mixly2/mixly2.0_src/issues/I8ZQ24) +- 修复 Python3程序运行错误,无错误提示. [\#IACRJ7](https://gitee.com/mixly2/mixly2.0_src/issues/IACRJ7) +- 更新 Arduino ESP32S3添加原理图. [\#I7X9LD](https://gitee.com/mixly2/mixly2.0_src/issues/I7X9LD) +- 更新 修改Arduino板卡中 `Serial.available() > 0` 为 `Serial.available()`. [\#I8BSZX](https://gitee.com/mixly2/mixly2.0_src/issues/I8BSZX) +- 更新 Arduino ESP32板卡中添加擦除flash功能. [\#IAE7AY](https://gitee.com/mixly2/mixly2.0_src/issues/IAE7AY) +- 更新 Electron更新到 `v31.2.1`,Blockly更新到 `v11.1.1`,Ace更新到 `v1.36.0`. +- 更新 Arduino和XPython板卡添加板卡文件管理功能. +- 重构 串口监视器和绘图器. +- 重构 使用ES6模块化重构所有默认板卡,扩展板卡构建时可通过 `npm install [板卡名]` 来安装默认板卡,以使用已有图形化模块. + - `@mixly/arduino`:[**v1.6.0**](https://www.npmjs.com/package/@mixly/arduino) + - `@mixly/arduino-avr`: [**v1.6.0**](https://www.npmjs.com/package/@mixly/arduino-avr) + - `@mixly/arduino-esp8266`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/arduino-esp8266) + - `@mixly/arduino-esp32`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/arduino-esp32) + - `@mixly/micropython`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython) + - `@mixly/micropython-esp32`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-esp32) + - `@mixly/micropython-esp32c2`: [**v1.4.0**](https://www.npmjs.com/package/@mixly/micropython-esp32c2) + - `@mixly/micropython-esp32c3`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-esp32c3) + - `@mixly/micropython-esp32s2`: [**v1.5.0**](https://www.npmjs.com/package/@mixly/micropython-esp32s2) + - `@mixly/micropython-esp32s3`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-esp32s3) + - `@mixly/micropython-robot`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/micropython-robot) + - `@mixly/micropython-k210-mixgoai`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-k210-mixgoai) + - `@mixly/micropython-nrf51822-microbit`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-nrf51822-microbit) + - `@mixly/micropython-nrf51822-mithoncc`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/micropython-nrf51822-mithoncc) + - `@mixly/python`: [**v1.1.0**](https://www.npmjs.com/package/@mixly/python) + - `@mixly/python-mixpy`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/python-mixpy) + - `@mixly/python-skulpt`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/python-skulpt) + - `@mixly/python-skulpt-car`: [**v1.1.0**](https://www.npmjs.com/package/@mixly/python-skulpt-car) + - `@mixly/python-skulpt-mixtoy`: [**v1.1.0**](https://www.npmjs.com/package/@mixly/python-skulpt-mixtoy) +- 重构 使用第三板卡和第三方库模板重构云端板卡和云端库 (部分),持续进行中... + - `QDPK210 AIstart`:[**mixly-board-micropython-k210-aistart**](https://gitee.com/mixly2-package/mixly-board-micropython-k210-aistart) + - `Teaile AIBIT`:[**mixly-board-micropython-k210-aibit**](https://gitee.com/mixly2-package/mixly-board-micropython-k210-aibit) + - `Teaile ESP32`:[**mixly-board-micropython-esp32-acbit**](https://gitee.com/mixly2-package/mixly-board-micropython-esp32-acbit) + - `TCTM KZB01`:[**mixly-board-micropython-esp32-tctm**](https://gitee.com/mixly2-package/mixly-board-micropython-esp32-tctm) + - `Arduino UNO R4`:[**mixly-board-arduino-unor4**](https://gitee.com/mixly2-package/mixly-board-arduino-unor4) + - `Arduino RP2040`:[**mixly-board-arduino-rp2040**](https://gitee.com/mixly2-package/mixly-board-arduino-rp2040) + - `Nulllab LGT328P`:[**mixly-board-nulllab-avr**](https://gitee.com/mixly2-package/mixly-board-nulllab-avr) + - `Arduino STM32`:[**mixly-board-arduino-stm32**](https://gitee.com/mixly2-package/mixly-board-arduino-stm32) + - `Bemfa`:[**mixly-lib-bemfa**](https://gitee.com/mixly2-package/mixly-lib-bemfa) + - `YFRobot`:[**mixly-lib-yfrobot**](https://gitee.com/mixly2-package/mixly-lib-yfrobot) + - `FileSystem`:[**mixly-lib-arduino-fs**](https://gitee.com/mixly2-package/mixly-lib-arduino-fs) + - `BlockBuildTool`:[**mixly-lib-block-build-tool**](https://gitee.com/mixly2-package/mixly-lib-block-build-tool) +- 开发 一些新的扩展板卡正在开发中... + - `Arduino CH55X`:[**mixly-board-arduino-ch55x**](https://gitee.com/mixly2-package/mixly-board-arduino-ch55x) + - `C STC`:[**mixly-board-c-stcxx**](https://gitee.com/mixly2-package/mixly-board-c-stcxx) + - `Lua xt804`:[**mixly-board-lua-xt804**](https://gitee.com/mixly2-package/mixly-board-lua-xt804) + - `Web Python3`:[**mixly-board-web-python3**](https://gitee.com/mixly2-package/mixly-board-web-python3) + +#### 2.0 rc4 2023-08-06 + +- 修复 Arduino ESP32C3 板载 WS2812 RGB灯编译出错. [\#I5P20N](https://gitee.com/mixly2/mixly2.0_src/issues/I5P20N) +- 修复 win7 32位 gcc版本不匹配. [#I5QOQO](https://gitee.com/mixly2/mixly2.0-win32-ia32/issues/I5QOQO) +- 修复 mac 下使用 Python ESP32-C3 初始化固件或上传时报错. [\#I5V5S3](https://gitee.com/mixly2/mixly2.0_src/issues/I5V5S3) +- 修复 Arduino AVR 板卡下 RGB 输入框和取色器 R、B 颜色反了. [\#I63AJJ](https://gitee.com/mixly2/mixly2.0_src/issues/I63AJJ) +- 修复 Arduino ESP32 板卡下当变量类型设置为布尔时上传错误. [\#I672R5](https://gitee.com/mixly2/mixly2.0_src/issues/I672R5) +- 修复 Arduino ESP32 硬件定时器导致系统不断重启. [\#I6B5WZ](https://gitee.com/mixly2/mixly2.0_src/issues/I6B5WZ) +- 修复 python3 语音技术运行报错. [\#I6B7AH](https://gitee.com/mixly2/mixly2.0-win32-x64/issues/I6B7AH) +- 修复 Arduino ESP32C3 下 串口图形块bug. [\#I6HUWN](https://gitee.com/mixly2/mixly2.0_src/issues/I6HUWN) +- 修复 代码区编辑代码后存本地,再打开后不会显示之前已编辑的代码. [\#I6JIM0](https://gitee.com/mixly2/mixly2.0_src/issues/I6JIM0) +- 修复 mac 下一键更新安装,Arduino编译提示 "bad CPU type in executable". [\#I6MNUY](https://gitee.com/mixly2/mixly2.0_src/issues/I6MNUY) +- 修复 mac Mixly2.0文本内容复制粘贴不了. [\#I6Z21S](https://gitee.com/mixly2/mixly2.0_src/issues/I6Z21S) +- 修复 windows Arduino ESP8266代码区无代码,无法编译. [\#I710YW](https://gitee.com/mixly2/mixly2.0_src/issues/I710YW) +- 更新 Arduino ESP32C3 GPIO添加11引脚. [\#I6X4L6](https://gitee.com/mixly2/mixly2.0_src/issues/I6X4L6) +- 更新 Blockly ( version: 10.0.2 ) + - `Blockly.Blocks.xxx.HUE` → `Blockly.Msg['xxx_HUE']` + - `Blockly.xxx` → `Blockly.Msg['xxx']` + - `Blockly.Mutator` → `Blockly.icons.MutatorIcon` + - `generator.xxx` → `generator.forBlock['xxx']` + +- 更新 XPython板卡和Arduino板卡 +- 更新 板卡管理工具和库管理工具 +- 更新 xpython板卡烧录所用python工具 +- 更新 `导出PNG` 选项移动到 Blockly 工作区右键菜单 +- 添加 右键菜单选项项 `添加注释`在 Blockly 工作区 +- 添加 墨水屏模块在 Arduino 板卡. [\#I670FM](https://gitee.com/mixly2/mixly2.0_src/issues/I670FM) +- 添加 用户配置项 + - 上传结束后自动打开串口. [\#I605PY](https://gitee.com/mixly2/mixly2.0_src/issues/I605PY) + - 主题调整为 "跟随系统"、"深色"、"浅色". [\#I692QN](https://gitee.com/mixly2/mixly2.0_src/issues/I692QN) +- 添加 消息栏在板卡页面 +- 添加 配置项说明在配置板卡栏 +- 添加 `此视图只读` 提示在状态栏和右侧代码预览区 ( `Enter`、`Del`、`Backspace` 触发 ) +- 添加 新功能在Blockly + - 工作区高亮 + - 工作区网格 + - 工作区缩略图 ( `实验性` ) + - 工作区多重选择 ( `实验性` - `Shift` + `鼠标左键` 触发 ) + - 渲染器切换 + +#### 2.0 rc3 2022-08-10 + +- 修复自代码区切换至模块区颜色选择模块尺寸改变 +- 修复串口操作导致窗口崩溃 +- 修复Blockly解析xml字符串报错 +- 修复Arduino下创建函数块右键生成函数块乱码 +- 修复双击文件打开程序不显示 +- 更新板卡管理工具和库管理工具 +- 更新Electron ( version: 19.0.6 ) +- 更新Ace、Ampy、Layui、fontello、skulpt、amWiki、fpJS +- 更新XPython板卡和Arduino板卡 +- 更新Mixly板卡页面布局 +- 更新配置Arduino板卡操作 +- 串口输出框、代码框添加右键菜单 +- 添加反馈、wiki、例程和图文转换按钮 +- 添加Blockly工具箱查找和工作区查找 +- 添加书包 +- 添加Blockly.FieldGridDropdown、Blockly.FieldBitmap和Blockly.FieldSlider + +#### 2.0 rc2 2022-03-19 + +- 修复ESP32数码管问题 +- 修复在图像化模块的注释打开时弹层位置不在窗口中央的问题 +- 修复导入本地第三方库错误 +- 尝试修复有时使用Blockly.Xml.textToDom函数报错 +- 尝试修复串口长时间使用时页面崩溃问题 +- 更新板卡micropython_esp32_handbit +- 更新板卡circuitpython_esp32s2_mixgocar +- 更新板卡micropython_k210_mixgoai +- 更新板卡micropython_esp32_mixgo +- 更新板卡micropython_nrf51822_microbit +- 更新板卡micropython_nrf51822_mithoncc +- 更新esptool ( version: 3.2 ) +- 更新Ampy +- 更新electron ( version: 17.1.2 ) +- 添加板卡micropython_esp32_mixgope +- 添加板卡micropython_esp32c3_mixgocar +- 添加板卡micropython_esp32c3_mixgocc +- 添加python_skulpt_mixtoy +- 添加【其他固件】按钮在xPython页面 +- 添加AI Thinker ESP32-CAM在Arduino ESP32 +- 添加过渡动画在板卡index切换时 +- 添加程序执行时间显示在python板卡状态栏 +- 调整头部工具栏 +- 调整各弹层在dark下的颜色 +- 自动获取category标签的id属性,不需要在code.js中手动添加 +- 移除Arduino STM32板卡,改为用户手动导入 +- 移除Arduino ESP32C3板卡不能使用的blynk,板载资源与蓝牙块 + +#### 2.0 rc1 2021-11-07 + +- 修复导入云端库时的一些问题 +- 修复库管理器对本地一些库无法进行管理的问题 +- 修复Arduino类板卡软串口错误 +- 修复python页面下生成代码存在很多空行的问题 +- 修复Arduino类板卡编译时中文输出为乱码的问题 +- 更新Arduino ESP32c3页面的串口配置和管脚定义 +- 更新CircuitPython MixGoCE与MixGoCar的固件 +- 更新MicroPython MixGoAI +- 增加通用旋转编码器图形化模块 +- 增加ESP系列红外解码图形化模块 +- 增加新板卡mPython +- 增加 "until" 及更新 "while" 图形化模块在xPython页面下 +- 增加OTA图形化模块在Arduino ESP页面下 +- 增加360°舵机和HCSR04超声波控制图形化模块在CricuitPython MixGoCE页面下 +- 增加折叠块在MixGoCE&MixGoCar页面下 +- 移除Arduino ESP页面下WIFI_AP&STA图形化模块 (变为云端导入) + +#### 2.0 rc0 2021-09-30 + +- 修复导入第三方库后切换语言一些第三方库语言没有改变 +- 修复CircuitPython MixGoCE界面下上传程序后状态栏不自动切换到串口输出 +- 注释串口读取时对连续两个数据时间间隔需大于50ms的限制 +- 更新CircuitPython MixGoCE与MixGoCar的固件 +- Arduino下增加对于mixio的支持 +- 添加Arduino ESP8266管脚映射图形化模块 +- 更新Arduino和Python第三方库url +- 取消导入库和板卡时的编辑url按钮 +- 板卡页面头部工具栏添加按钮点击效果 +- 同步弹出打开、保存文件窗口改为异步弹出 +- Arduino类板卡页面支持云端导入Arduino库文件和管理本地Arduino库文件 +- Python类板卡页面支持云端导入py文件和管理本地py文件 + +#### 2.0 Beta14 2021-09-14 + +- 修复软件主题设为dark时从主页面到板卡页面会有短暂闪屏 +- 修复Arduino类板卡下blynk分类下一些模块无法生成代码 +- 修复Arduino ESP8266板卡下红外通信模块生成代码编译报错 +- 修复Arduino ESP32板卡下使用ESP32 CAM相关模块编译报错 +- 修复设置语言后刷新页面会变成默认语言的问题 +- 修复Arduino类板卡下编译上传时报错信息会显示两次 +- 修复串口工具读取数据时会剔除空行的问题 +- 更新CircuitPython MixGoCE与MixGoCar的固件和相关图形化模块 +- 更新electron版本到13.3.0 +- 更新blockly版本到6.20210701.0 +- 更换主页面背景图片 +- 板卡页面更改语言后支持动态更新页面 +- 板卡页面导入和删除第三方库后支持动态更新左侧工具箱 +- 主页面导入和删除板卡后支持动态更新页面 +- 完善软件对多国语言的支持 +- Arduino类板卡编译和上传时支持同时编译所打开MIX、INO所在目录下的[*.h, *.hpp, *.c, *.cpp]文件 + +#### 2.0 Beta13 2021-08-26 + +- 修复Arduino AVR板卡下Blynk连接状态函数无法生成代码的问题 +- 修复MicroPython MixGo AI板卡在串口工具打开时复位按钮无法使用的问题 +- 修复microPython和CircuitPython下数学分类下某些模块生成代码上传报错的问题 +- 修复打开和保存文件时默认路径有时不为sample文件夹的问题 +- 修复py下if-else & try-except使用ctrl+z后报错的问题 +- 修复初始化固件或上传程序后有时遮罩无法关闭的问题 +- 修复串口读取数据时无法解码中文编码字符串的问题 +- 调整板卡配置文件 +- CircuitPython MixGo CE板卡下添加Mixly Key、获取cpu温度、NTP时间和SD卡操作图形化模块 +- 更新CircuitPython MixGo CE板卡固件 +- 更新状态栏,支持在状态栏中显示串口号 +- 更新板卡页面头部工具栏 +- Arduino板卡下支持导出和导入已编译的bin、hex文件 + +#### 2.0 Beta12 2021-08-14 + +- 修复Arduino页面下函数声明模块无法被禁用的问题 +- 修复侧边代码框和代码编辑框字体大小不同步的问题 +- 修复MixGo AI下有时程序卡住时无法再上传的的问题 +- 修复串口接收数据为中文时有乱码问题 +- 修复主页面下显示多行板卡时有时某几行板卡无法显示的问题 +- 修复Microbit下舵机和蜂鸣器无法使用的问题 +- 更新Mixgo CE 和 MixGo Car图形化模块及其固件 +- 更新例程 +- 支持双击文件在Mixly中打开(需要先关联MIX文件到Mixly) +- 串口监视器添加DTR和RTS设置 + +#### 2.0 Beta11 2021-08-06 + +- 修复Arduino ESP8266和ESP32板卡页面blynk模块编译报错问题 +- 修复MixGoAI板卡使用kflash工具烧录时的报错问题 +- 修复Arduino ESP8266和ESP32界面下使用本地导入库后无第三方模块的问题 +- 修复主页面下显示的板卡在高分辨率屏幕上排列会出错的问题 +- 修复串口在读取数据时如果没有换行符数据不会显示的问题 +- Arduino ESP32S2板卡页面增加USB串口程序块 +- Arduino ESP32S2和ESP32C3板卡页面添加GPIO图 +- 更新Sample下例程版本为Mixly2.0 +- 更新MixGo CE和MixGo Car下图形化模块和所用固件 +- 添加py模块pgzero +- Arduino STM32支持使用Mixly烧录固件 + +#### 2021-08-01 + +- 修复保存文件后不显示保存路径的问题 +- 修复当软件路径中含有空格时编译、烧录和上传操作会出错的问题 +- 尝试修复导入Mxixly1.x所用第三方库有些分类无法显示的问题 +- 更新MixGo CE和MixGo Car下图形化模块和所用固件 + +#### 2021-07-30 + +- 同步Mixly1.x下Arduino类图形化模块 +- 添加新板卡Arduino ESP32S2和ESP32C3 + +#### 2021-07-29 + +- 添加主进程调试工具electron-dev-console +- 添加新板卡Arduino MixGo CE + +#### 2021-07-28 + +- 修复Mac和Linux下通过VID、PID无法筛选串口的问题 +- 修复Linux下通过盘符号获取路径出错的问题 + +#### 2021-07-27 + +- 修复在打开两个及以上窗口时启动速度变慢的问题 +- 串口工具支持拖拽改变尺寸 +- 添加本地快捷键 + | Mixly2.0客户端界面操作 | 快捷键 | + | :--------------------: | :----: | + | 打开新页面 | Ctrl+N | + +#### 2021-07-26 + +- 更新云端板卡TCTM KZB01 +- 更新本地快捷键 + | Mixly2.0客户端界面操作 | 快捷键 | + | :--------------------: | :----------: | + | 缩小页面 | Ctrl+Shift+- | + +#### 2021-07-25 + +- 修复K210板卡使用ampy上传有时会失败的问题 +- Mac系统下使用which python3命令获取已安装python3的路径 +- 支持使用ampy递归上传文件 + +#### 2021-07-24 + +- 添加新板卡MixGo AI +- 更新云端板卡TCTM KZB01 +- 添加本地快捷键 + | Mixly2.0客户端界面操作 | 快捷键 | + | :--------------------: | :----: | + | 打开更新日志 | Ctrl+H | + +#### 2021-07-22 + +- 添加新板卡MixGo Car + +#### 2021-07-21 + +- 修复Arduino界面下LCD1602编译出错问题 +- 修复Arduino界面OLED分类下模块下拉图片链接出错的问题 +- 修复Arduino界面下模块SDA、SCL等管脚无法使用默认配置的问题 + +#### 2021-07-20 + +- 修复导入第三方库后在开发者模式下无法查看已导入第三方库js文件的问题 + +#### 2021-07-17 + +- 修复本地导入板卡和第三方库按钮不可用问题 + +#### 2021-07-16 + +- 修复Microbit和Mithon页面下【保存HEX】按钮文字不显示的问题 +- 修复Win下ESP32板卡编译失败的问题 +- 支持同时对多个同类型板卡进行固件烧录或程序上传操作 + +#### 2021-07-14 + +- 修复Arduino页面下缩小窗口时编译按钮不折叠的问题 +- 串口绘图支持绘制多条折线 +- 添加本地快捷键 + | Mixly2.0客户端界面操作 | 快捷键 | + | :--------------------: | :----------: | + | 还原页面 | Ctrl+0 | + | 放大页面 | Ctrl+Shift+= | + | 缩小页面 | Ctrl+- | + +#### 2021-07-10 + +- 添加云端板卡MicroPython_esp32_TCTM_KZB01 + +#### 2021-07-09 + +- 添加测试板卡MicroPython_K210_MaixDock + +#### 2021-07-07 + +- 支持用户自定义arduinoCli和Python3的路径,当在默认路径下未检测到对应软件时,会使用自定义路径 + +#### 2021-07-05 + +- 添加K210固件烧录工具kflash + +#### 2021-07-04 + +- 添加本地快捷键 + | Mixly2.0客户端界面操作 | 快捷键 | + | :--------------------: | :----------: | + | 打开或关闭开发者工具 | Ctrl+Shift+I | + | 重载页面 | Ctrl+R | + | 最小化窗口 | Ctrl+M | + | 关闭窗口 | Ctrl+W | +- 修复在打开两个及以上窗口时会出现短暂白屏问题 + +#### 2021-07-01 + +- Mixly 网页端MixGo板卡使用WebSerial上传 +- Mixly 网页端MixGo和MixGoCE板卡固件烧录采用WebSerial ESPTool +- 尝试修复MixGoCE上传结束后的灰屏问题 + +#### 2021-06-19 + +- 修复microbit界面TCS34725颜色传感器模块读取RGB数据出错的问题 +- 配置文件支持添加多个盘符 +- 状态栏支持通过快捷键设置字体大小、发送Ctrl+C和Ctrl+D、清空状态栏 + | 状态栏操作 | 快捷键 | + | :--------: | :------------: | + | 增大字体 | Ctrl-=\|Ctrl-+ | + | 减小字体 | Ctrl+-\|Ctrl- | + | 发送Ctrl+C | Ctrl+Shift+C | + | 发送Ctrl+D | Ctrl+Shift+D | + | 清空状态栏 | Ctrl+E | + +#### 2021-05-29 + +- 修复侧边代码框向左拖动时宽度无限制的问题 +- 修复打开文件或在文本转图形时图形化模块无法居中的问题 +- 修复打开文件后左侧分类树无法自动复位的问题 +- 修复主题设为dark时进入板卡页面后主题依然为light的问题 + +#### 2021-05-13 + +- 修复打开mix文件显示“无效的xml”的问题 +- 修复保存png文件后无法打开的问题 +- 修复串口输出介于[-1,1]的数字会读取出错的问题 +- 修复有多个串口时无法正常切换串口的问题 +- 修复板卡页面主题设为dark后左侧分类树字体颜色为黑的问题 +- 更新MixGo CE页面图形块及固件 + +#### 2021-05-09 + +- 修复主页面在改变窗口尺寸或屏幕分辨率后板卡会堆叠在一起的问题 +- 修复板卡页面鼠标滚轮缩放速率过大的问题 +- 使用node https替换request模块 + +#### 2021-04-19 + +- 修复Arduino界面终止编译/上传后状态栏仍会继续显示部分编译/上传信息 +- 修复点击“打开”按钮时未选择文件则会清除当前文件路径的问题 +- 修复打开文件显示invalid xml file!时会清除工作区和代码区程序的问题 +- 修复打开文件后退出板卡页面再次进入会丢失文件路径的问题 +- 修复从板卡页面退出轮播索引会自动设为0的问题 + +#### 2021-04-18 + +- 修复打开文件显示invalid xml file!时仍会显示文件路径的问题 +- 修复打开文件显示invalid xml file!时代码区仍会显示部分代码的问题 +- 修复状态栏和工作区在主题为dark时无效果的问题 +- 修复代码区代码在退出页面后再次进入无法恢复的问题 +- 修复设置语言后重启软件会变回默认语言的问题 +- 修复Arduino界面板卡切换后工作区图形化模块管脚不会同步的问题 +- 使用Arduino-CLI替换Arduino IDE,加快编译和上传速度,目前已添加AVR板卡 +- MixGoCE 外接元件/传感器、物联网分类下模块添加文本转图形 + +#### 2021-04-16 + +- 修复重复打开相同文件时不会读取文件数据的问题 +- 修复python界面input模块输入中文时输出乱码的问题 +- 修复python和micropython界面在包含类与对象相关模块时会出错的问题 +- 更新“保存”、“另存为”、“新建”、“打开”操作 +- 更新串口可视化 +- 串口和头部工具栏支持用户使用config.json来配置 +- 缓存文件支持不同界面数据分开储存 + +#### 2021-04-12 + +- 更新“保存”、“另存为”按钮 +- 修复MixGo按RST后无法上传的问题 +- 串口加上关闭/打开按钮 + +#### 2021-04-08 + +- 修复板卡选择下拉框展开时展开框不居中的问题 +- 修复释放头部工具栏中某个按钮后此按钮依旧为按下状态的问题 +- 调整串口、状态框、编译、烧录、上传等相关函数 + +#### 2021-04-02 + +- 串口选择下拉框支持显示多行 +- 修复非MixGOCE、microbit、mithon板卡的串口切换错误问题 +- 初始化固件、上传支持记住上一次选择的串口或盘符号 +- 板卡切换按钮设置为一直显示 + +#### 2021-03-21 + +- RGB灯带的逻辑修改为官网逻辑 +- python编辑器自动缩进为4个空格 +- 修复缩小窗口时文字重叠问题 +- 去掉了初始化超声波图形模块 +- 更新串口工具 +- 修复串口短时间获取大量数据时卡死问题 +- 支持在软件内动态添加板卡,支持直接在软件内删除板卡 +- 暂时只添加了Arduino AVR板卡 +- 添加MixGo板卡 +- 添加导入库、管理库、切换板卡按钮,暂时不支持导入库、管理库、切换板卡操作 +- 添加Shift+Ctrl+C和Shift+Ctrl+V操作 +- MixGo上传采用python-shell调用ampy工具 +- MixGo和MixGoCE烧录固件采用python-shell调用esptool工具 \ No newline at end of file diff --git a/mixly/LICENSE b/mixly/LICENSE new file mode 100644 index 00000000..c8920c15 --- /dev/null +++ b/mixly/LICENSE @@ -0,0 +1,3 @@ + 本软件使用了Electron,Node.JS,Blockly,Skulpt,Arduino,Micropython,CircuitPython,ESP-IDF,Arduino-cli,Arduino-ESP32,,Arduino-ESP8266等一大堆开源软件,用户在使用是必须遵守上述开源软件各种的License,除此以外,除非与上述协议冲突,否则,任何使用本代码的用户和组织在修改后必须保留Mixly这一软件名称及作者信息,但可以使用Mixly4XXX这样的名字,XXX就是使用者自己的名字。 + + This software uses a large number of open source software such as Electron, Node.JS, Blockly, Skulpt, Arduino, Micropython,CircuitPython, ESP-IDF, Arduino-cli, Arduino-ESP32, Arduino-ESP8266, etc. The user must comply with the above open source software's Licenses, in addition, Unless it conflicts with the above Licenses, any user or organization using this code must retain the name of the Software and author information after modification, but may use a name such as Mixly4XXX, which is the user's own name. diff --git a/mixly/boards/HDK/MixGo CC-V3.2.pdf b/mixly/boards/HDK/MixGo CC-V3.2.pdf new file mode 100644 index 00000000..79dbef24 Binary files /dev/null and b/mixly/boards/HDK/MixGo CC-V3.2.pdf differ diff --git a/mixly/boards/HDK/MixGo CE-V3.7.pdf b/mixly/boards/HDK/MixGo CE-V3.7.pdf new file mode 100644 index 00000000..d65f93e7 Binary files /dev/null and b/mixly/boards/HDK/MixGo CE-V3.7.pdf differ diff --git a/mixly/boards/HDK/MixGo ME-V2.3.pdf b/mixly/boards/HDK/MixGo ME-V2.3.pdf new file mode 100644 index 00000000..d273b6a8 Binary files /dev/null and b/mixly/boards/HDK/MixGo ME-V2.3.pdf differ diff --git a/mixly/boards/HDK/MixGo Nova-V2.6.pdf b/mixly/boards/HDK/MixGo Nova-V2.6.pdf new file mode 100644 index 00000000..21aa51be Binary files /dev/null and b/mixly/boards/HDK/MixGo Nova-V2.6.pdf differ diff --git a/mixly/boards/HDK/MixGo_MINI-V1.7.pdf b/mixly/boards/HDK/MixGo_MINI-V1.7.pdf new file mode 100644 index 00000000..c1375140 Binary files /dev/null and b/mixly/boards/HDK/MixGo_MINI-V1.7.pdf differ diff --git a/mixly/boards/default/micropython/build/HZK12.bin b/mixly/boards/default/micropython/build/HZK12.bin new file mode 100644 index 00000000..215c1825 Binary files /dev/null and b/mixly/boards/default/micropython/build/HZK12.bin differ diff --git a/mixly/boards/default/micropython/build/HZK16.bin b/mixly/boards/default/micropython/build/HZK16.bin new file mode 100644 index 00000000..fd7b4c72 Binary files /dev/null and b/mixly/boards/default/micropython/build/HZK16.bin differ diff --git a/mixly/boards/default/micropython/build/HZK16_GBK.bin b/mixly/boards/default/micropython/build/HZK16_GBK.bin new file mode 100644 index 00000000..2965cdb8 Binary files /dev/null and b/mixly/boards/default/micropython/build/HZK16_GBK.bin differ diff --git a/mixly/boards/default/micropython/build/esp_tts_voice_data_xiaole.dat b/mixly/boards/default/micropython/build/esp_tts_voice_data_xiaole.dat new file mode 100644 index 00000000..a406c868 Binary files /dev/null and b/mixly/boards/default/micropython/build/esp_tts_voice_data_xiaole.dat differ diff --git a/mixly/boards/default/micropython/build/esp_tts_voice_data_xiaoxin.dat b/mixly/boards/default/micropython/build/esp_tts_voice_data_xiaoxin.dat new file mode 100644 index 00000000..ed150c2b Binary files /dev/null and b/mixly/boards/default/micropython/build/esp_tts_voice_data_xiaoxin.dat differ diff --git a/mixly/boards/default/micropython/build/lib/adafruit_miniqr.py b/mixly/boards/default/micropython/build/lib/adafruit_miniqr.py new file mode 100644 index 00000000..f8fcb04c --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/adafruit_miniqr.py @@ -0,0 +1,602 @@ +# SPDX-FileCopyrightText: 2009 Kazuhiko Arase +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Ported from the Javascript library by Sam Curren +# QRCode for Javascript +# http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/qrcode.js +# +# Minimized for CircuitPython by ladyada for adafruit industries +# +# The word "QR Code" is registered trademark of +# DENSO WAVE INCORPORATED +# http://www.denso-wave.com/qrcode/faqpatent-e.html +""" +`adafruit_miniqr` +==================================================== + +A non-hardware dependant miniature QR generator library. All native Python! + +* Author(s): ladyada + +Implementation Notes +-------------------- + +**Hardware:** + +* Any! + +**Software and Dependencies:** + +* Python 3 + +""" + +# imports +import math + +try: + from typing import Dict, List, Optional, Tuple +except ImportError: + pass + +__version__ = "0.0.0+auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_miniQR.git" + +# Consts! +M = 0 +L = 1 +H = 2 +Q = 3 + +_MODE_8BIT_BYTE = 1 << 2 +_PAD0 = 0xEC +_PAD1 = 0x11 + +# Optimized polynomial helpers + + +def _glog(n: int) -> int: + """Lookup log(n) from pre-calculated byte table""" + if n < 1: + raise ValueError("glog(" + n + ")") + return LOG_TABLE[n] + + +def _gexp(n: int) -> int: + """Lookup exp(n) from pre-calculated byte table""" + while n < 0: + n += 255 + while n >= 256: + n -= 255 + return EXP_TABLE[n] + + +EXP_TABLE = b"\x01\x02\x04\x08\x10 @\x80\x1d:t\xe8\xcd\x87\x13&L\x98-Z\xb4u\xea\xc9\x8f\x03\x06\x0c\x180`\xc0\x9d'N\x9c%J\x945j\xd4\xb5w\xee\xc1\x9f#F\x8c\x05\n\x14(P\xa0]\xbai\xd2\xb9o\xde\xa1_\xbea\xc2\x99/^\xbce\xca\x89\x0f\x1e|\xf8\xed\xc7\x93;v\xec\xc5\x973f\xcc\x85\x17.\\\xb8m\xda\xa9O\x9e!B\x84\x15*T\xa8M\x9a)R\xa4U\xaaI\x929r\xe4\xd5\xb7s\xe6\xd1\xbfc\xc6\x91?~\xfc\xe5\xd7\xb3{\xf6\xf1\xff\xe3\xdb\xabK\x961b\xc4\x957n\xdc\xa5W\xaeA\x82\x192d\xc8\x8d\x07\x0e\x1c8p\xe0\xdd\xa7S\xa6Q\xa2Y\xb2y\xf2\xf9\xef\xc3\x9b+V\xacE\x8a\t\x12$H\x90=z\xf4\xf5\xf7\xf3\xfb\xeb\xcb\x8b\x0b\x16,X\xb0}\xfa\xe9\xcf\x83\x1b6l\xd8\xadG\x8e\x01" # noqa: E501 + +LOG_TABLE = b"\x00\x00\x01\x19\x022\x1a\xc6\x03\xdf3\xee\x1bh\xc7K\x04d\xe0\x0e4\x8d\xef\x81\x1c\xc1i\xf8\xc8\x08Lq\x05\x8ae/\xe1$\x0f!5\x93\x8e\xda\xf0\x12\x82E\x1d\xb5\xc2}j'\xf9\xb9\xc9\x9a\txM\xe4r\xa6\x06\xbf\x8bbf\xdd0\xfd\xe2\x98%\xb3\x10\x91\"\x886\xd0\x94\xce\x8f\x96\xdb\xbd\xf1\xd2\x13\\\x838F@\x1eB\xb6\xa3\xc3H~nk:(T\xfa\x85\xba=\xca^\x9b\x9f\n\x15y+N\xd4\xe5\xacs\xf3\xa7W\x07p\xc0\xf7\x8c\x80c\rgJ\xde\xed1\xc5\xfe\x18\xe3\xa5\x99w&\xb8\xb4|\x11D\x92\xd9# \x89.7?\xd1[\x95\xbc\xcf\xcd\x90\x87\x97\xb2\xdc\xfc\xbea\xf2V\xd3\xab\x14*]\x9e\x84<9SGmA\xa2\x1f-C\xd8\xb7{\xa4v\xc4\x17I\xec\x7f\x0co\xf6l\xa1;R)\x9dU\xaa\xfb`\x86\xb1\xbb\xcc>Z\xcbY_\xb0\x9c\xa9\xa0Q\x0b\xf5\x16\xebzu,\xd7O\xae\xd5\xe9\xe6\xe7\xad\xe8t\xd6\xf4\xea\xa8PX\xaf" # noqa: E501 + + +class QRCode: + """The generator class for QR code matrices""" + + def __init__(self, *, qr_type: Optional[int] = None, error_correct: int = L): + """Initialize an empty QR code. You can define the `qr_type` (size) + of the code matrix, or have the libary auto-select the smallest + match. Default `error_correct` is type L (7%), but you can select M, + Q or H.""" + self.type = qr_type + self.ECC = error_correct + self.matrix = None + self.module_count = 0 + self.data_cache = None + self.data_list = [] + + def add_data(self, data: bytes) -> None: + """Add more data to the QR code, must be bytestring stype""" + self.data_list.append(data) + datalen = sum(len(x) for x in self.data_list) + if not self.type: + for qr_type in range(1, 10): + rs_blocks = _get_rs_blocks(qr_type, self.ECC) + total_data_count = 0 + for block in rs_blocks: + total_data_count += block["data"] + if total_data_count > datalen: + self.type = qr_type + break + self.data_cache = None + + def make(self, *, test: bool = False, mask_pattern: int = 0) -> None: + """Perform the actual generation of the QR matrix. To keep things + small and speedy we don't generate all 8 mask patterns and pick + the best. Instead, please pass in a desired mask_pattern, the + default mask is 0.""" + self.module_count = self.type * 4 + 17 + self.matrix = QRBitMatrix(self.module_count, self.module_count) + + self._setup_position_probe_pattern(0, 0) + self._setup_position_probe_pattern(self.module_count - 7, 0) + self._setup_position_probe_pattern(0, self.module_count - 7) + self._setup_position_adjust_pattern() + self._setup_timing_pattern() + self._setup_type_info(test, mask_pattern) + + if self.type >= 7: + self._setup_type_number(test) + + if self.data_cache is None: + self.data_cache = QRCode._create_data(self.type, self.ECC, self.data_list) + self._map_data(self.data_cache, mask_pattern) + + def _setup_position_probe_pattern(self, row: int, col: int) -> None: + """Add the positition probe data pixels to the matrix""" + for r in range(-1, 8): + if row + r <= -1 or self.module_count <= row + r: + continue + for c in range(-1, 8): + if col + c <= -1 or self.module_count <= col + c: + continue + test = ( + (0 <= r <= 6 and (c in (0, 6))) + or (0 <= c <= 6 and (r in (0, 6))) + or (2 <= r <= 4 and 2 <= c <= 4) + ) + self.matrix[row + r, col + c] = test + + def _setup_timing_pattern(self) -> None: + """Add the timing data pixels to the matrix""" + for r in range(8, self.module_count - 8): + if self.matrix[r, 6] is not None: + continue + self.matrix[r, 6] = r % 2 == 0 + + for c in range(8, self.module_count - 8): + if self.matrix[6, c] is not None: + continue + self.matrix[6, c] = c % 2 == 0 + + def _setup_position_adjust_pattern(self) -> None: + """Add the position adjust data pixels to the matrix""" + pos = QRUtil.get_pattern_position(self.type) + + for row in pos: + for col in pos: + if self.matrix[row, col] is not None: + continue + + for r in range(-2, 3): + for c in range(-2, 3): + test = abs(r) == 2 or abs(c) == 2 or (r == 0 and c == 0) + self.matrix[row + r, col + c] = test + + def _setup_type_number(self, test: bool) -> None: + """Add the type number pixels to the matrix""" + bits = QRUtil.get_BCH_type_number(self.type) + + for i in range(18): + mod = not test and ((bits >> i) & 1) == 1 + self.matrix[i // 3, i % 3 + self.module_count - 8 - 3] = mod + + for i in range(18): + mod = not test and ((bits >> i) & 1) == 1 + self.matrix[i % 3 + self.module_count - 8 - 3, i // 3] = mod + + def _setup_type_info(self, test: bool, mask_pattern: int) -> None: + """Add the type info pixels to the matrix""" + data = (self.ECC << 3) | mask_pattern + bits = QRUtil.get_BCH_type_info(data) + + # // vertical + for i in range(15): + mod = not test and ((bits >> i) & 1) == 1 + if i < 6: + self.matrix[i, 8] = mod + elif i < 8: + self.matrix[i + 1, 8] = mod + else: + self.matrix[self.module_count - 15 + i, 8] = mod + + # // horizontal + for i in range(15): + mod = not test and ((bits >> i) & 1) == 1 + if i < 8: + self.matrix[8, self.module_count - i - 1] = mod + elif i < 9: + self.matrix[8, 15 - i - 1 + 1] = mod + else: + self.matrix[8, 15 - i - 1] = mod + + # // fixed module + self.matrix[self.module_count - 8, 8] = not test + + def _map_data(self, data: bytes, mask_pattern: int) -> None: + """Map the data onto the QR code""" + inc = -1 + row = self.module_count - 1 + bit_idx = 7 + byte_idx = 0 + + for col in range(self.module_count - 1, 0, -2): + if col == 6: + col -= 1 # noqa: PLW2901 loop variable overwritten + + while True: + for c in range(2): + if self.matrix[row, col - c] is None: + dark = False + if byte_idx < len(data): + dark = ((data[byte_idx] >> bit_idx) & 1) == 1 + mask = QRUtil.get_mask(mask_pattern, row, col - c) + if mask: + dark = not dark + self.matrix[row, col - c] = dark + bit_idx -= 1 + if bit_idx == -1: + byte_idx += 1 + bit_idx = 7 + row += inc + if row < 0 or self.module_count <= row: + row -= inc + inc = -inc + break + + @staticmethod + def _create_data(qr_type: int, ecc: int, data_list: list) -> bytes: + """Check and format data into bit buffer""" + rs_blocks = _get_rs_blocks(qr_type, ecc) + + buffer = QRBitBuffer() + + for data in data_list: + if isinstance(data, str): + data = str.encode(data) # noqa: PLW2901 loop variable overwritten + buffer.put(_MODE_8BIT_BYTE, 4) + buffer.put(len(data), 8) + for byte in data: + buffer.put(byte, 8) + + # // calc num max data. + total_data_count = 0 + for block in rs_blocks: + total_data_count += block["data"] + + if buffer.get_length_bits() > total_data_count * 8: + raise RuntimeError( + "Code length overflow: %d > %d" % (buffer.get_length_bits(), total_data_count * 8) + ) + + # // end code + if buffer.get_length_bits() + 4 <= total_data_count * 8: + buffer.put(0, 4) + + # // padding + while buffer.get_length_bits() % 8 != 0: + buffer.put_bit(False) + + # // padding + while True: + if buffer.get_length_bits() >= total_data_count * 8: + break + buffer.put(_PAD0, 8) + if buffer.get_length_bits() >= total_data_count * 8: + break + buffer.put(_PAD1, 8) + + return QRCode._create_bytes(buffer, rs_blocks) + + @staticmethod + def _create_bytes(buffer: bytes, rs_blocks: List[Dict]) -> bytes: # noqa: PLR0912 Too many branches + """Perform error calculation math on bit buffer""" + + offset = 0 + max_dc_count = 0 + max_ec_count = 0 + + dcdata = [0] * len(rs_blocks) + ecdata = [0] * len(rs_blocks) + + for r, block in enumerate(rs_blocks): + dc_count = block["data"] + ec_count = block["total"] - dc_count + + max_dc_count = max(max_dc_count, dc_count) + max_ec_count = max(max_ec_count, ec_count) + + dcdata[r] = [0] * dc_count + + for i in range(len(dcdata[r])): + dcdata[r][i] = 0xFF & buffer.buffer[i + offset] + offset += dc_count + + rs_poly = QRUtil.get_error_correct_polynomial(ec_count) + mod_poly = QRPolynomial(dcdata[r], rs_poly.get_length() - 1) + + while True: + if mod_poly.get_length() - rs_poly.get_length() < 0: + break + ratio = _glog(mod_poly.get(0)) - _glog(rs_poly.get(0)) + num = [0 for x in range(mod_poly.get_length())] + for i in range(mod_poly.get_length()): + num[i] = mod_poly.get(i) + for i in range(rs_poly.get_length()): + num[i] ^= _gexp(_glog(rs_poly.get(i)) + ratio) + mod_poly = QRPolynomial(num, 0) + + ecdata[r] = [0 for x in range(rs_poly.get_length() - 1)] + for i in range(len(ecdata[r])): + mod_index = i + mod_poly.get_length() - len(ecdata[r]) + if mod_index >= 0: + ecdata[r][i] = mod_poly.get(mod_index) + else: + ecdata[r][i] = 0 + + total_code_count = 0 + for block in rs_blocks: + total_code_count += block["total"] + + data = [None] * total_code_count + index = 0 + + for i in range(max_dc_count): + for r in range(len(rs_blocks)): + if i < len(dcdata[r]): + data[index] = dcdata[r][i] + index += 1 + + for i in range(max_ec_count): + for r in range(len(rs_blocks)): + if i < len(ecdata[r]): + data[index] = ecdata[r][i] + index += 1 + + return data + + +class QRUtil: + """A selection of bit manipulation tools for QR generation and BCH encoding""" + + PATTERN_POSITION_TABLE = [ + b"", + b"\x06\x12", + b"\x06\x16", + b"\x06\x1a", + b"\x06\x1e", + b'\x06"', + b"\x06\x16&", + b"\x06\x18*", + b"\x06\x1a.", + b"\x06\x1c2", + ] + + G15 = 0b10100110111 + G18 = 0b1111100100101 + G15_MASK = 0b101010000010010 + + @staticmethod + def get_BCH_type_info(data: int) -> int: + """Encode with G15 BCH mask""" + d = data << 10 + while QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G15) >= 0: + d ^= QRUtil.G15 << (QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G15)) + + return ((data << 10) | d) ^ QRUtil.G15_MASK + + @staticmethod + def get_BCH_type_number(data: int) -> int: + """Encode with G18 BCH mask""" + d = data << 12 + while QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G18) >= 0: + d ^= QRUtil.G18 << (QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G18)) + return (data << 12) | d + + @staticmethod + def get_BCH_digit(data: int) -> int: + """Count digits in data""" + digit = 0 + while data != 0: + digit += 1 + data >>= 1 + return digit + + @staticmethod + def get_pattern_position(qr_type: int) -> bytes: + """The mask pattern position array for this QR type""" + return QRUtil.PATTERN_POSITION_TABLE[qr_type - 1] + + @staticmethod + def get_mask(mask: int, i: int, j: int) -> int: # noqa: PLR0911 Too many return statements + """Perform matching calculation on two vals for given pattern mask""" + if mask == 0: + return (i + j) % 2 == 0 + if mask == 1: + return i % 2 == 0 + if mask == 2: + return j % 3 == 0 + if mask == 3: + return (i + j) % 3 == 0 + if mask == 4: + return (math.floor(i / 2) + math.floor(j / 3)) % 2 == 0 + if mask == 5: + return (i * j) % 2 + (i * j) % 3 == 0 + if mask == 6: + return ((i * j) % 2 + (i * j) % 3) % 2 == 0 + if mask == 7: + return ((i * j) % 3 + (i + j) % 2) % 2 == 0 + raise ValueError("Bad mask pattern:" + mask) + + @staticmethod + def get_error_correct_polynomial(ecc_length: int) -> "QRPolynomial": + """Generate a ecc polynomial""" + poly = QRPolynomial([1], 0) + for i in range(ecc_length): + poly = poly.multiply(QRPolynomial([1, _gexp(i)], 0)) + return poly + + +class QRPolynomial: + """Structure for creating and manipulating error code polynomials""" + + def __init__(self, num: int, shift: int): + """Create a QR polynomial""" + if not num: + raise ValueError(num.length + "/" + shift) + offset = 0 + while offset < len(num) and num[offset] == 0: + offset += 1 + self.num = [0 for x in range(len(num) - offset + shift)] + for i in range(len(num) - offset): + self.num[i] = num[i + offset] + + def get(self, index: int) -> int: + """The exponent at the index location""" + return self.num[index] + + def get_length(self) -> int: + """Length of the poly""" + return len(self.num) + + def multiply(self, other_polynomial: "QRPolynomial") -> "QRPolynomial": + """Multiply two polynomials, returns a new one""" + num = [0 for x in range(self.get_length() + other_polynomial.get_length() - 1)] + + for i in range(self.get_length()): + for j in range(other_polynomial.get_length()): + num[i + j] ^= _gexp(_glog(self.get(i)) + _glog(other_polynomial.get(j))) + + return QRPolynomial(num, 0) + + +_QRRS_BLOCK_TABLE = ( + b"\x01\x1a\x10", + b"\x01\x1a\x13", + b"\x01\x1a\t", + b"\x01\x1a\r", + b"\x01,\x1c", + b'\x01,"', + b"\x01,\x10", + b"\x01,\x16", + b"\x01F,", + b"\x01F7", + b"\x02#\r", + b"\x02#\x11", + b"\x022 ", + b"\x01dP", + b"\x04\x19\t", + b"\x022\x18", + b"\x02C+", + b"\x01\x86l", + b'\x02!\x0b\x02"\x0c', + b'\x02!\x0f\x02"\x10', + b"\x04+\x1b", + b"\x02VD", + b"\x04+\x0f", + b"\x04+\x13", + b"\x041\x1f", + b"\x02bN", + b"\x04'\r\x01(\x0e", + b"\x02 \x0e\x04!\x0f", + b"\x02<&\x02='", + b"\x02ya", + b"\x04(\x0e\x02)\x0f", + b"\x04(\x12\x02)\x13", + b"\x03:$\x02;%", + b"\x02\x92t", + b"\x04$\x0c\x04%\r", + b"\x04$\x10\x04%\x11", +) + + +def _get_rs_blocks(qr_type: int, ecc: int) -> List[Dict]: + rs_block = _QRRS_BLOCK_TABLE[(qr_type - 1) * 4 + ecc] + + length = len(rs_block) // 3 + blocks = [] + for i in range(length): + count = rs_block[i * 3 + 0] + total = rs_block[i * 3 + 1] + data = rs_block[i * 3 + 2] + block = {"total": total, "data": data} + for _ in range(count): + blocks.append(block) + return blocks + + +class QRBitMatrix: + """A bit-packed storage class for matrices""" + + def __init__(self, width: int, height: int): + self.width = width + self.height = height + if width > 60: + raise ValueError("Max 60 bits wide:", width) + self.buffer = [0] * self.height * 2 + self.used = [0] * self.height * 2 + + def __repr__(self) -> str: + b = "" + for y in range(self.height): + for x in range(self.width): + if self[x, y]: + b += "X" + else: + b += "." + b += "\n" + return b + + def __getitem__(self, key: Tuple[int, int]) -> int: + x, y = key + if y > self.width: + raise ValueError() + i = 2 * x + (y // 30) + j = y % 30 + if not self.used[i] & (1 << j): + return None + return self.buffer[i] & (1 << j) + + def __setitem__(self, key: Tuple[int, int], value: int) -> None: + x, y = key + if y > self.width: + raise ValueError() + i = 2 * x + (y // 30) + j = y % 30 + if value: + self.buffer[i] |= 1 << j + else: + self.buffer[i] &= ~(1 << j) + self.used[i] |= 1 << j # buffer item was set + + +class QRBitBuffer: + """Storage class for a length of individual bits""" + + def __init__(self): + self.buffer = [] + self.length = 0 + + def __repr__(self) -> str: + return ".".join([str(n) for n in self.buffer]) + + def get(self, index: int) -> int: + """The bit value at a location""" + i = index // 8 + return self.buffer[i] & (1 << (7 - index % 8)) + + def put(self, num: int, length: int) -> None: + """Add a number of bits from a single integer value""" + for i in range(length): + self.put_bit(num & (1 << (length - i - 1))) + + def get_length_bits(self) -> int: + """Size of bit buffer""" + return self.length + + def put_bit(self, bit: int) -> None: + """Insert one bit at the end of the bit buffer""" + i = self.length // 8 + if len(self.buffer) <= i: + self.buffer.append(0) + if bit: + self.buffer[i] |= 0x80 >> (self.length % 8) + self.length += 1 diff --git a/mixly/boards/default/micropython/build/lib/adxl345.py b/mixly/boards/default/micropython/build/lib/adxl345.py new file mode 100644 index 00000000..32952553 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/adxl345.py @@ -0,0 +1,52 @@ +#ADXL345 +import time +import ustruct +from micropython import const + +DATA_FORMAT = const(0x31) +BW_RATE = const(0x2c) +POWER_CTL = const(0x2d) +INT_ENABLE = const(0x2E) +OFSX = const(0x1e) +OFSY = const(0x1f) +OFSZ = const(0x20) + +class ADXL345: + def __init__(self, i2c, address=0X53): + self._device = i2c + self._address = address + if self._rreg(0x0) != 0xe5: + raise AttributeError("Cannot find a ADXL345") + + self._wreg(DATA_FORMAT,0x2B) #16g量程 + self._wreg(BW_RATE,0x0A) #数据输出速度为100Hz + self._wreg(INT_ENABLE,0x00) #不使用中断 + + self._wreg(OFSX,0x00) + self._wreg(OFSY,0x00) + self._wreg(OFSZ,0x00) + self._wreg(POWER_CTL,0x08) #链接使能,测量模式 + time.sleep(0.5) + + def readXYZ(self): + x, = ustruct.unpack('= self._delay: + self._star = time.ticks_ms() + _buf = self._rreg(_AGS10_ADC) + self._voc = int.from_bytes(_buf[1:4], 'big') + self.ready = not (_buf[0] & 0x01) + return self._voc / 1000 + + def read(self, hcho_mw=30.033 , co2_mv=0.853, co2_base=400): + '''unit ppm''' + self.getdata + _voc = self._voc / 1000 #ppm + return round( _voc, 2), round( _voc / hcho_mw, 2), co2_base + round( _voc / co2_mv, 2) + + def tvoc(self): + return self.read()[0] + + def hcho(self, tvoc_mw=30.053): + return self.read(hcho_mw=hcho_mw)[1] + + def eco2(self, co2_mv=0.853): + return self.read(co2_mv=co2_mv)[2] diff --git a/mixly/boards/default/micropython/build/lib/ahtx0.py b/mixly/boards/default/micropython/build/lib/ahtx0.py new file mode 100644 index 00000000..d7887283 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ahtx0.py @@ -0,0 +1,88 @@ +""" +AHT21 + +Micropython library for the AHT21(temperature,humidity) +======================================================= + +#Changed from circuitpython to micropython 20220211 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" +import utime +from micropython import const + +AHTX0_I2CADDR_DEFAULT = const(0x38) # Default I2C address +AHTX0_CMD_INITIALIZE = const(0xE1) # Initialization command +AHTX0_CMD_TRIGGER = const(0xAC) # Trigger reading command +AHTX0_CMD_SOFTRESET = const(0xBA) # Soft reset command +AHTX0_STATUS_BUSY = const(0x80) # Status bit for busy +AHTX0_STATUS_CALIBRATED = const(0x08) # Status bit for calibrated + +class AHTx0: + """Interface library for AHT10/AHT20 temperature+humidity sensors""" + def __init__(self, i2c, address=AHTX0_I2CADDR_DEFAULT): + utime.sleep_ms(20) # 20ms delay to wake up + self._i2c = i2c + self._address = address + self._buf = bytearray(6) + self.reset() + if not self.initialize(): + raise AttributeError("Cannot find a AHTx0") + self._temp = None + self._humidity = None + + def reset(self): + """Perform a soft-reset of the AHT""" + self._buf[0] = AHTX0_CMD_SOFTRESET + self._i2c.writeto(self._address, self._buf[0:1]) + utime.sleep_ms(20) # 20ms delay to wake up + + def initialize(self): + """Ask the sensor to self-initialize. Returns True on success, False otherwise""" + self._buf[0] = AHTX0_CMD_INITIALIZE + self._buf[1] = 0x08 + self._buf[2] = 0x00 + self._i2c.writeto(self._address, self._buf[0:3]) + self._wait_for_idle() + if not self.status() & AHTX0_STATUS_CALIBRATED: + return False + return True + + def status(self): + """The status byte initially returned from the sensor, see datasheet for details""" + self._read_to_buffer() + return self._buf[0] + + def _read_to_buffer(self): + self._i2c.readfrom_into(self._address, self._buf) + + def _trigger_measurement(self): + """Internal function for triggering the AHT to read temp/humidity""" + self._buf[0] = AHTX0_CMD_TRIGGER + self._buf[1] = 0x33 + self._buf[2] = 0x00 + self._i2c.writeto(self._address, self._buf[0:3]) + + def _wait_for_idle(self): + while self.status() & AHTX0_STATUS_BUSY: + utime.sleep_ms(5) + + def _perform_measurement(self): + self._trigger_measurement() + self._wait_for_idle() + self._read_to_buffer() + + def humidity(self): + """The measured relative humidity in percent.""" + self._perform_measurement() + self._humidity = (self._buf[1] << 12) | (self._buf[2] << 4) | (self._buf[3] >> 4) + self._humidity = (self._humidity * 100) / 0x100000 + return self._humidity + + def temperature(self): + """The measured temperature in degrees Celcius.""" + self._perform_measurement() + self._temp = ((self._buf[3] & 0xF) << 16) | (self._buf[4] << 8) | self._buf[5] + self._temp = ((self._temp * 200.0) / 0x100000) - 50 + return self._temp \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/ap3216c.py b/mixly/boards/default/micropython/build/lib/ap3216c.py new file mode 100644 index 00000000..111b9c33 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ap3216c.py @@ -0,0 +1,59 @@ +""" +AP3216C + +MicroPython library for the AP3216C(ALS,PS,IRS) +======================================================= +#Preliminary composition 20240630 + +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +AP3216_ADD = const(0x1E) +AP_SYS_CMD = const(0x00) +AP_DAT = const(0x0A) +AP_ALS_CMD = const(0x10) +AP_PS_CMD = const(0x20) +AP_PS_LED = const(0x21) +Resolution = 0.35 + +class AP3216C: + def __init__(self, i2c_bus, addr=AP3216_ADD): + self._device = i2c_bus + self._address = addr + self._wreg(AP_SYS_CMD, 0x04) # SW reset + time.sleep_ms(100) + self._wreg(AP_SYS_CMD, 0x03) # 011: ALS and PS+IR functions active + self._wreg(AP_ALS_CMD, 0x00) # Range 1: 0 ~ 20661 Lux. Resolution = 0.35 lux/count. + self._wreg(AP_PS_CMD, 0x09) # PS gain:10 + self._wreg(AP_PS_LED, 0x23) # PS LED pulse:10 + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + @property + def getdata(self): + '''处理获取数据''' + #buf = self._rreg(AP_DAT, 6) + ir = (self._rreg(AP_DAT + 0) & 0x03) | self._rreg(AP_DAT + 1) << 2 + als= (self._rreg(AP_DAT + 2) | self._rreg(AP_DAT + 3) << 8) * Resolution + ps = (self._rreg(AP_DAT + 4) & 0x0F) | (self._rreg(AP_DAT + 5) & 0x3F) << 4 + return round(als, 2), ir, ps + + def als_vis(self): + '''可见光Lux''' + return self.getdata[0] + + def als_ir(self): + '''红外Lux''' + return self.getdata[1] + + def ps_nl(self): + '''接近距离''' + return self.getdata[2] diff --git a/mixly/boards/default/micropython/build/lib/apds9960.py b/mixly/boards/default/micropython/build/lib/apds9960.py new file mode 100644 index 00000000..af4c4400 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/apds9960.py @@ -0,0 +1,294 @@ +""" +APDS9960` + +MicroPython library for the APDS9960(Supports gesture, proximity, and color detection) +======================================================= + +#Preliminary composition 20220224 +#base on https://github.com/adafruit/Adafruit_CircuitPython_BusDevice 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +_DEVICE_ID = const(0xAB) +_APDS9960_ENABLE = const(0x80) +_APDS9960_ATIME = const(0x81) +_APDS9960_PILT = const(0x89) +_APDS9960_PIHT = const(0x8B) +_APDS9960_PERS = const(0x8C) +_APDS9960_CONTROL = const(0x8F) +_APDS9960_ID = const(0x92) +_APDS9960_STATUS = const(0x93) +_APDS9960_CDATAL = const(0x94) +_APDS9960_PDATA = const(0x9C) +_APDS9960_GPENTH = const(0xA0) +_APDS9960_GEXTH = const(0xA1) +_APDS9960_GCONF1 = const(0xA2) +_APDS9960_GCONF2 = const(0xA3) +_APDS9960_GPULSE = const(0xA6) +_APDS9960_GCONF4 = const(0xAB) +_APDS9960_GFLVL = const(0xAE) +_APDS9960_GSTATUS = const(0xAF) +_APDS9960_AICLEAR = const(0xE7) +_APDS9960_GFIFO_U = const(0xFC) +_BIT_MASK_ENABLE_EN = const(0x01) +_BIT_MASK_ENABLE_COLOR = const(0x02) +_BIT_MASK_ENABLE_PROX = const(0x04) +_BIT_MASK_ENABLE_PROX_INT = const(0x20) +_BIT_MASK_ENABLE_GESTURE = const(0x40) +_BIT_MASK_STATUS_AVALID = const(0x01) +_BIT_MASK_STATUS_GINT = const(0x04) +_BIT_MASK_GSTATUS_GFOV = const(0x02) +_BIT_MASK_GCONF4_GFIFO_CLR = const(0x04) +_BIT_POS_PERS_PPERS = const(4) +_BIT_MASK_PERS_PPERS = const(0xF0) +_BIT_POS_CONTROL_AGAIN = const(0) +_BIT_MASK_CONTROL_AGAIN = const(3) +_BIT_POS_CONTROL_PGAIN = const(2) +_BIT_MASK_CONTROL_PGAIN = const(0x0C) +_BIT_POS_GCONF2_GGAIN = const(5) +_BIT_MASK_GCONF2_GGAIN = const(0x60) + +class APDS9960: + def __init__(self, i2c, address=0x39): + self._device = i2c + self._address = address + self._select = [True,True,True] + + if self._rreg(_APDS9960_ID) != _DEVICE_ID: + raise AttributeError("Cannot find a APDS9960") + + self.enable(True) # Re-enable sensor and wait 10ms for the power on delay to finish + time.sleep(0.010) + self._wreg(_APDS9960_GPENTH, 0x05) # Enter gesture engine at >= 5 proximity counts + self._wreg(_APDS9960_GEXTH, 0x1E) # Exit gesture engine if all counts drop below 30 + self._wreg(_APDS9960_GCONF1, 0x82) # GEXPERS: 2 (4 cycles), GEXMSK: 0 (default) GFIFOTH: 2 (8 datasets) + self._wreg(_APDS9960_GCONF2, 0x41) # GGAIN: 2 (4x), GLDRIVE: 100 mA (default), GWTIME: 1 (2.8ms) + self._wreg(_APDS9960_GPULSE, 0x85) # GPULSE: 5 (6 pulses), GPLEN: 2 (16 us) + self.color_integration_time(256) # ATIME: 256 (712ms color integration time, max count of 65535) + + # method for reading and writing to I2C + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _writecmdonly(self, val): + """Writes a command and 0 bytes of data to the I2C device""" + self._device.writeto(self._address,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _get_bit(self, reg, mask): + """Gets a single bit value from the I2C device's register""" + return bool(self._rreg(reg) & mask) + + def _set_bit(self, reg, mask, value): + """Sets a single bit value in the I2C device's register""" + buf=self._rreg(reg) + buf= buf | mask if value else buf & ~mask + self._wreg(reg,buf) + + def _set_bits(self, reg, pos, mask, value): + """Sets a multi-bit value in the I2C device's register""" + buf=self._rreg(reg) + buf = (buf & ~mask) | (value << pos) + self._wreg(reg,buf) + + def _color_data16(self, reg): + """Sends a command and reads 2 bytes of data from the I2C device""" + buf = self._rreg(reg,2) + return buf[1] << 8 | buf[0] + + def enable(self, value): + """sensor is enabled""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_EN, value) + + def enable_proximity(self, value): + """sensor's proximity engine is enabled.""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_PROX, value) + + def proximity_gain(self, value): + """""Proximity sensor gain value""" + # proximity_gain" "Gain Multiplier" "Note" + # 0, "1x", "Power-on Default" + # 1, "2x", "" + # 2, "4x", "" + # 3, "8x", "" + self._set_bits(_APDS9960_CONTROL, _BIT_POS_CONTROL_PGAIN, _BIT_MASK_CONTROL_PGAIN, value) + + def enable_gesture(self, value): + """sensor's gesture engine is enabled""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_GESTURE, value) + + def gesture_gain(self, value): + """Gesture mode gain value""" + # "gesture_gain" "Gain Multiplier" "Note" + # 0, "1x", "Power-on Default" + # 1, "2x", "" + # 2, "4x", "Driver Default" + # 3, "8x", "" + self._set_bits(_APDS9960_GCONF2, _BIT_POS_GCONF2_GGAIN, _BIT_MASK_GCONF2_GGAIN, value) + + def enable_color(self, value): + """sensor's color/light engine is enabled""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_COLOR, value) + + def color_gain(self, value): + """Color/light sensor gain value""" + # "color_gain" "Gain Multiplier" "Note" + # 0, "1x", "Power-on Default" + # 1, "4x", "Driver Default" + # 2, "16x", "" + # 3, "64x", "" + self._set_bits(_APDS9960_CONTROL, _BIT_POS_CONTROL_AGAIN, _BIT_MASK_CONTROL_AGAIN, value) + + def color_integration_time(self, value): + """Color/light sensor gain""" + # "color_integration_time" "Time" "Max Count" "Note" + # 1, "2.78 ms", 1025, "Power-on Default" + # 10, "27.8 ms", 10241, "" + # 37, "103 ms", 37889, "" + # 72, "200 ms", 65535, "" + # 256, "712 ms", 65535, "Driver Default" + self._wreg(_APDS9960_ATIME, 256 - value) + + ## PROXIMITY + def proximity(self,gain=2): + """Proximity sensor data""" + if self._select[0]: + self._select=[False,True,True] + self.enable_proximity(True) + self.enable_gesture(False) + self.enable_color(False) + self.proximity_gain(gain) + + return self._rreg(_APDS9960_PDATA) + + ## GESTURE + def gesture(self,gain=3): + """Gesture sensor data""" + # If FIFOs have overflowed we're already way too late, so clear those FIFOs and wait + if self._select[1]: + self._select=[True,False,True] + self.enable_proximity(True) + self.enable_gesture(True) + self.enable_color(False) + self.gesture_gain(gain) + + if self._get_bit(_APDS9960_GSTATUS, _BIT_MASK_GSTATUS_GFOV): + self._set_bit(_APDS9960_GCONF4, _BIT_MASK_GCONF4_GFIFO_CLR, True) + wait_cycles = 0 + while ( not self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_GINT) and wait_cycles <= 30 ): + time.sleep(0.003) + wait_cycles += 1 + + frame = [] + datasets_available = self._rreg(_APDS9960_GFLVL) + if (self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_GINT) and datasets_available > 0 ): + + buffer = bytearray(128) + buffer_dataset = bytearray(4) + while True: + dataset_count = self._rreg(_APDS9960_GFLVL) + if dataset_count == 0: + break + buffer=self._rreg(_APDS9960_GFIFO_U,min(128, 1 + (dataset_count * 4))) + # Unpack data stream into more usable U/D/L/R datasets for analysis + idx = 0 + for i in range(dataset_count): + idx = i * 4 + buffer_dataset[0] = buffer[idx] + buffer_dataset[1] = buffer[idx + 1] + buffer_dataset[2] = buffer[idx + 2] + buffer_dataset[3] = buffer[idx + 3] + + if ((not all(val == 255 for val in buffer_dataset)) + and (not all(val == 0 for val in buffer_dataset)) + and (all(val >= 30 for val in buffer_dataset)) + ): + if len(frame) < 2: + frame.append(tuple(buffer_dataset)) + else: + frame[1] = tuple(buffer_dataset) + time.sleep(0.03) + if len(frame) < 2: + return None + # Determine our up/down and left/right ratios along with our first/last deltas + f_r_ud = ((frame[0][0] - frame[0][1]) * 100) // (frame[0][0] + frame[0][1]) + f_r_lr = ((frame[0][2] - frame[0][3]) * 100) // (frame[0][2] + frame[0][3]) + l_r_ud = ((frame[1][0] - frame[1][1]) * 100) // (frame[1][0] + frame[1][1]) + l_r_lr = ((frame[1][2] - frame[1][3]) * 100) // (frame[1][2] + frame[1][3]) + delta_ud = l_r_ud - f_r_ud + delta_lr = l_r_lr - f_r_lr + # Make our first guess at what gesture we saw, if any + state_ud = 0 + state_lr = 0 + if delta_ud >= 30: + state_ud = 1 + elif delta_ud <= -30: + state_ud = -1 + + if delta_lr >= 30: + state_lr = 1 + elif delta_lr <= -30: + state_lr = -1 + # Make our final decision based on our first guess and, if required, the delta data + gesture_found = 0 + # Easy cases + if state_ud == -1 and state_lr == 0: + gesture_found = 1 + elif state_ud == 1 and state_lr == 0: + gesture_found = 2 + elif state_ud == 0 and state_lr == -1: + gesture_found = 3 + elif state_ud == 0 and state_lr == 1: + gesture_found = 4 + # Not so easy cases + if gesture_found == 0: + if state_ud == -1 and state_lr == 1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 1 + else: + gesture_found = 4 + elif state_ud == 1 and state_lr == -1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 2 + else: + gesture_found = 3 + elif state_ud == -1 and state_lr == -1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 1 + else: + gesture_found = 3 + elif state_ud == 1 and state_lr == 1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 2 + else: + gesture_found = 3 + + dir_lookup = [None,"left", "right", "down", "up"] + return dir_lookup[gesture_found] + + ## COLOR + def color(self,gain=1): + """Tuple containing red, green, blue, and clear light intensity values""" + if self._select[2]: + self._select=[True,True,False] + self.enable_proximity(False) + self.enable_gesture(False) + self.enable_color(True) + self.color_gain(gain) + + while not self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_AVALID): + time.sleep(0.005) #"""Color data ready flag""" + return ( + self._color_data16(_APDS9960_CDATAL + 2), + self._color_data16(_APDS9960_CDATAL + 4), + self._color_data16(_APDS9960_CDATAL + 6), + self._color_data16(_APDS9960_CDATAL), + ) diff --git a/mixly/boards/default/micropython/build/lib/baidu_speech.py b/mixly/boards/default/micropython/build/lib/baidu_speech.py new file mode 100644 index 00000000..d45b2cc9 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/baidu_speech.py @@ -0,0 +1,114 @@ +""" +Baidu ASR API + +MicroPython library for Baidu ASR API +======================================================= + +#Preliminary composition 20230223 +#https://ai.baidu.com/ai-doc/SPEECH/Ek39uxgre +#https://ai.baidu.com/unit/home#/home + +@dahanzimin From the Mixly Team +""" + +import json,gc +import urequests,array +from ubinascii import hexlify +from machine import Timer,unique_id + +'''Set constant''' +_framerate=8000 +_unique_id=hexlify(unique_id()).decode() + +def urequests_api(method, url, **kw): + '''Request data''' + try: + return json.loads(urequests.request(method, url, **kw).text) + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected",e) + +def fetch_token(API_Key,Secret_Key): + """Get access_token""" + url='http://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={}&client_secret={}'.format(API_Key,Secret_Key) + results=urequests_api("GET",url) + if "error_description" in results.keys(): + raise ValueError(results["error_description"]) + if "access_token" in results.keys(): + return results["access_token"] + +class Recorder: + def __init__(self, adc,timer=2): + self._timer=Timer(timer) + self._mic=adc + + def _timer_callback(self,timer): + '''Timer callback read microphone''' + try: + _mic=self._mic.read_u16()-32768 + self._pcm_buffer.append(_mic &0xFF) + self._pcm_buffer.append(_mic >>8) + self._record_time-=1 + except: + print("Warning: MemoryError!") + self._pcm_buffer=bytearray() + gc.collect() + self._record_time=0 + + def record(self,record_time=1): + """Call timer to record audio""" + self._pcm_buffer=bytearray() + gc.collect() + self._record_time=record_time*_framerate + self._timer.init(freq =_framerate, mode = Timer.PERIODIC, callback = self._timer_callback) + while True: + if self._record_time <= 0: + self._timer.deinit() + gc.collect() + return self._pcm_buffer + +class ASR(Recorder): + def __init__(self, adc, API_Key, Secret_Key, timer=2): + self._token=fetch_token(API_Key,Secret_Key) + super().__init__(adc,timer) + + def recognize(self,record_time=1,dev_pid=1537): + """Access API to get voice results""" + pcm_buffer=self.record(record_time) + if max(pcm_buffer)>=250: + url='http://vop.baidu.com/server_api?dev_pid={}&cuid={}&token={}'.format(dev_pid,_unique_id,self._token) + headers = {'Content-Type': 'audio/pcm; rate={}'.format(_framerate)} + results=urequests_api("POST",url,data=pcm_buffer,headers=headers) + if results["err_no"] != 0: + raise ValueError(results["err_msg"],results["err_no"]) + elif results["err_msg"] == "success.": + gc.collect() + return results["result"][0] + else: + return '' + +class UNIT: + def __init__(self, API_Key, Secret_Key): + self._token=fetch_token(API_Key,Secret_Key) + self._session_id="" + + def chatbot(self,chatbot_id,query): + """Access API to intelligent dialog""" + if len(query) > 0: + url='https://aip.baidubce.com/rpc/2.0/unit/service/v3/chat?access_token={}'.format(self._token) + data={"log_id":"log"+_unique_id, + "version":"3.0", + "service_id":chatbot_id, + "session_id":self._session_id, + "request":{"query":query,"terminal_id":_unique_id}} + headers = {"content-type": "application/json"} + results=urequests_api("POST",url,data=json.dumps(data).encode(),headers=headers) + if results["error_code"] != 0: + raise ValueError(results["error_msg"],results["error_code"]) + elif results["error_msg"] == "success": + self._session_id=results["result"]['session_id'] + gc.collect() + return results["result"]['responses'][0]['actions'][0]['say'] + else: + return '' + +gc.collect() diff --git a/mixly/boards/default/micropython/build/lib/base64.py b/mixly/boards/default/micropython/build/lib/base64.py new file mode 100644 index 00000000..d6baca05 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/base64.py @@ -0,0 +1,480 @@ +#! /usr/bin/env python3 + +"""RFC 3548: Base16, Base32, Base64 Data Encodings""" + +# Modified 04-Oct-1995 by Jack Jansen to use binascii module +# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support +# Modified 22-May-2007 by Guido van Rossum to use bytes everywhere + +import re +import struct +import binascii + + +__all__ = [ + # Legacy interface exports traditional RFC 1521 Base64 encodings + "encode", + "decode", + "encodebytes", + "decodebytes", + # Generalized interface for other encodings + "b64encode", + "b64decode", + "b32encode", + "b32decode", + "b16encode", + "b16decode", + # Standard Base64 encoding + "standard_b64encode", + "standard_b64decode", + # Some common Base64 alternatives. As referenced by RFC 3458, see thread + # starting at: + # + # http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html + "urlsafe_b64encode", + "urlsafe_b64decode", +] + + +bytes_types = (bytes, bytearray) # Types acceptable as binary data + + +def _bytes_from_decode_data(s): + if isinstance(s, str): + try: + return s.encode("ascii") + # except UnicodeEncodeError: + except: + raise ValueError("string argument should contain only ASCII characters") + elif isinstance(s, bytes_types): + return s + else: + raise TypeError("argument should be bytes or ASCII string, not %s" % s.__class__.__name__) + + +def _maketrans(f, t): + """Re-implement bytes.maketrans() as there is no such function in micropython""" + if len(f) != len(t): + raise ValueError("maketrans arguments must have same length") + translation_table = dict(zip(f, t)) + return translation_table + + +def _translate(input_bytes, trans_table): + """Re-implement bytes.translate() as there is no such function in micropython""" + result = bytearray() + + for byte in input_bytes: + translated_byte = trans_table.get(byte, byte) + result.append(translated_byte) + + return bytes(result) + + +# Base64 encoding/decoding uses binascii + + +def b64encode(s, altchars=None): + """Encode a byte string using Base64. + + s is the byte string to encode. Optional altchars must be a byte + string of length 2 which specifies an alternative alphabet for the + '+' and '/' characters. This allows an application to + e.g. generate url or filesystem safe Base64 strings. + + The encoded byte string is returned. + """ + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + # Strip off the trailing newline + encoded = binascii.b2a_base64(s)[:-1] + if altchars is not None: + if not isinstance(altchars, bytes_types): + raise TypeError("expected bytes, not %s" % altchars.__class__.__name__) + assert len(altchars) == 2, repr(altchars) + encoded = _translate(encoded, _maketrans(b"+/", altchars)) + return encoded + + +def b64decode(s, altchars=None, validate=False): + """Decode a Base64 encoded byte string. + + s is the byte string to decode. Optional altchars must be a + string of length 2 which specifies the alternative alphabet used + instead of the '+' and '/' characters. + + The decoded string is returned. A binascii.Error is raised if s is + incorrectly padded. + + If validate is False (the default), non-base64-alphabet characters are + discarded prior to the padding check. If validate is True, + non-base64-alphabet characters in the input result in a binascii.Error. + """ + s = _bytes_from_decode_data(s) + if altchars is not None: + altchars = _bytes_from_decode_data(altchars) + assert len(altchars) == 2, repr(altchars) + s = _translate(s, _maketrans(altchars, b"+/")) + if validate and not re.match(b"^[A-Za-z0-9+/]*=*$", s): + raise binascii.Error("Non-base64 digit found") + return binascii.a2b_base64(s) + + +def standard_b64encode(s): + """Encode a byte string using the standard Base64 alphabet. + + s is the byte string to encode. The encoded byte string is returned. + """ + return b64encode(s) + + +def standard_b64decode(s): + """Decode a byte string encoded with the standard Base64 alphabet. + + s is the byte string to decode. The decoded byte string is + returned. binascii.Error is raised if the input is incorrectly + padded or if there are non-alphabet characters present in the + input. + """ + return b64decode(s) + + +# _urlsafe_encode_translation = _maketrans(b'+/', b'-_') +# _urlsafe_decode_translation = _maketrans(b'-_', b'+/') + + +def urlsafe_b64encode(s): + """Encode a byte string using a url-safe Base64 alphabet. + + s is the byte string to encode. The encoded byte string is + returned. The alphabet uses '-' instead of '+' and '_' instead of + '/'. + """ + # return b64encode(s).translate(_urlsafe_encode_translation) + return b64encode(s, b"-_").rstrip(b"\n") + + +def urlsafe_b64decode(s): + """Decode a byte string encoded with the standard Base64 alphabet. + + s is the byte string to decode. The decoded byte string is + returned. binascii.Error is raised if the input is incorrectly + padded or if there are non-alphabet characters present in the + input. + + The alphabet uses '-' instead of '+' and '_' instead of '/'. + """ + # s = _bytes_from_decode_data(s) + # s = s.translate(_urlsafe_decode_translation) + # return b64decode(s) + raise NotImplementedError() + + +# Base32 encoding/decoding must be done in Python +_b32alphabet = { + 0: b"A", + 9: b"J", + 18: b"S", + 27: b"3", + 1: b"B", + 10: b"K", + 19: b"T", + 28: b"4", + 2: b"C", + 11: b"L", + 20: b"U", + 29: b"5", + 3: b"D", + 12: b"M", + 21: b"V", + 30: b"6", + 4: b"E", + 13: b"N", + 22: b"W", + 31: b"7", + 5: b"F", + 14: b"O", + 23: b"X", + 6: b"G", + 15: b"P", + 24: b"Y", + 7: b"H", + 16: b"Q", + 25: b"Z", + 8: b"I", + 17: b"R", + 26: b"2", +} + +_b32tab = [v[0] for k, v in sorted(_b32alphabet.items())] +_b32rev = dict([(v[0], k) for k, v in _b32alphabet.items()]) + + +def b32encode(s): + """Encode a byte string using Base32. + + s is the byte string to encode. The encoded byte string is returned. + """ + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + quanta, leftover = divmod(len(s), 5) + # Pad the last quantum with zero bits if necessary + if leftover: + s = s + bytes(5 - leftover) # Don't use += ! + quanta += 1 + encoded = bytearray() + for i in range(quanta): + # c1 and c2 are 16 bits wide, c3 is 8 bits wide. The intent of this + # code is to process the 40 bits in units of 5 bits. So we take the 1 + # leftover bit of c1 and tack it onto c2. Then we take the 2 leftover + # bits of c2 and tack them onto c3. The shifts and masks are intended + # to give us values of exactly 5 bits in width. + c1, c2, c3 = struct.unpack("!HHB", s[i * 5 : (i + 1) * 5]) + c2 += (c1 & 1) << 16 # 17 bits wide + c3 += (c2 & 3) << 8 # 10 bits wide + encoded += bytes( + [ + _b32tab[c1 >> 11], # bits 1 - 5 + _b32tab[(c1 >> 6) & 0x1F], # bits 6 - 10 + _b32tab[(c1 >> 1) & 0x1F], # bits 11 - 15 + _b32tab[c2 >> 12], # bits 16 - 20 (1 - 5) + _b32tab[(c2 >> 7) & 0x1F], # bits 21 - 25 (6 - 10) + _b32tab[(c2 >> 2) & 0x1F], # bits 26 - 30 (11 - 15) + _b32tab[c3 >> 5], # bits 31 - 35 (1 - 5) + _b32tab[c3 & 0x1F], # bits 36 - 40 (1 - 5) + ] + ) + # Adjust for any leftover partial quanta + if leftover == 1: + encoded = encoded[:-6] + b"======" + elif leftover == 2: + encoded = encoded[:-4] + b"====" + elif leftover == 3: + encoded = encoded[:-3] + b"===" + elif leftover == 4: + encoded = encoded[:-1] + b"=" + return bytes(encoded) + + +def b32decode(s, casefold=False, map01=None): + """Decode a Base32 encoded byte string. + + s is the byte string to decode. Optional casefold is a flag + specifying whether a lowercase alphabet is acceptable as input. + For security purposes, the default is False. + + RFC 3548 allows for optional mapping of the digit 0 (zero) to the + letter O (oh), and for optional mapping of the digit 1 (one) to + either the letter I (eye) or letter L (el). The optional argument + map01 when not None, specifies which letter the digit 1 should be + mapped to (when map01 is not None, the digit 0 is always mapped to + the letter O). For security purposes the default is None, so that + 0 and 1 are not allowed in the input. + + The decoded byte string is returned. binascii.Error is raised if + the input is incorrectly padded or if there are non-alphabet + characters present in the input. + """ + s = _bytes_from_decode_data(s) + quanta, leftover = divmod(len(s), 8) + if leftover: + raise binascii.Error("Incorrect padding") + # Handle section 2.4 zero and one mapping. The flag map01 will be either + # False, or the character to map the digit 1 (one) to. It should be + # either L (el) or I (eye). + if map01 is not None: + map01 = _bytes_from_decode_data(map01) + assert len(map01) == 1, repr(map01) + s = _translate(s, _maketrans(b"01", b"O" + map01)) + if casefold: + s = s.upper() + # Strip off pad characters from the right. We need to count the pad + # characters because this will tell us how many null bytes to remove from + # the end of the decoded string. + padchars = s.find(b"=") + if padchars > 0: + padchars = len(s) - padchars + s = s[:-padchars] + else: + padchars = 0 + + # Now decode the full quanta + parts = [] + acc = 0 + shift = 35 + for c in s: + val = _b32rev.get(c) + if val is None: + raise binascii.Error("Non-base32 digit found") + acc += _b32rev[c] << shift + shift -= 5 + if shift < 0: + parts.append(binascii.unhexlify(bytes("%010x" % acc, "ascii"))) + acc = 0 + shift = 35 + # Process the last, partial quanta + last = binascii.unhexlify(bytes("%010x" % acc, "ascii")) + if padchars == 0: + last = b"" # No characters + elif padchars == 1: + last = last[:-1] + elif padchars == 3: + last = last[:-2] + elif padchars == 4: + last = last[:-3] + elif padchars == 6: + last = last[:-4] + else: + raise binascii.Error("Incorrect padding") + parts.append(last) + return b"".join(parts) + + +# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns +# lowercase. The RFC also recommends against accepting input case +# insensitively. +def b16encode(s): + """Encode a byte string using Base16. + + s is the byte string to encode. The encoded byte string is returned. + """ + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + return binascii.hexlify(s).upper() + + +def b16decode(s, casefold=False): + """Decode a Base16 encoded byte string. + + s is the byte string to decode. Optional casefold is a flag + specifying whether a lowercase alphabet is acceptable as input. + For security purposes, the default is False. + + The decoded byte string is returned. binascii.Error is raised if + s were incorrectly padded or if there are non-alphabet characters + present in the string. + """ + s = _bytes_from_decode_data(s) + if casefold: + s = s.upper() + if re.search(b"[^0-9A-F]", s): + raise binascii.Error("Non-base16 digit found") + return binascii.unhexlify(s) + + +# Legacy interface. This code could be cleaned up since I don't believe +# binascii has any line length limitations. It just doesn't seem worth it +# though. The files should be opened in binary mode. + +MAXLINESIZE = 76 # Excluding the CRLF +MAXBINSIZE = (MAXLINESIZE // 4) * 3 + + +def encode(input, output): + """Encode a file; input and output are binary files.""" + while True: + s = input.read(MAXBINSIZE) + if not s: + break + while len(s) < MAXBINSIZE: + ns = input.read(MAXBINSIZE - len(s)) + if not ns: + break + s += ns + line = binascii.b2a_base64(s) + output.write(line) + + +def decode(input, output): + """Decode a file; input and output are binary files.""" + while True: + line = input.readline() + if not line: + break + s = binascii.a2b_base64(line) + output.write(s) + + +def encodebytes(s): + """Encode a bytestring into a bytestring containing multiple lines + of base-64 data.""" + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + pieces = [] + for i in range(0, len(s), MAXBINSIZE): + chunk = s[i : i + MAXBINSIZE] + pieces.append(binascii.b2a_base64(chunk)) + return b"".join(pieces) + + +def encodestring(s): + """Legacy alias of encodebytes().""" + import warnings + + warnings.warn("encodestring() is a deprecated alias, use encodebytes()", DeprecationWarning, 2) + return encodebytes(s) + + +def decodebytes(s): + """Decode a bytestring of base-64 data into a bytestring.""" + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + return binascii.a2b_base64(s) + + +def decodestring(s): + """Legacy alias of decodebytes().""" + import warnings + + warnings.warn("decodestring() is a deprecated alias, use decodebytes()", DeprecationWarning, 2) + return decodebytes(s) + + +# Usable as a script... +def main(): + """Small main program""" + import sys, getopt + + try: + opts, args = getopt.getopt(sys.argv[1:], "deut") + except getopt.error as msg: + sys.stdout = sys.stderr + print(msg) + print( + """usage: %s [-d|-e|-u|-t] [file|-] + -d, -u: decode + -e: encode (default) + -t: encode and decode string 'Aladdin:open sesame'""" + % sys.argv[0] + ) + sys.exit(2) + func = encode + for o, a in opts: + if o == "-e": + func = encode + if o == "-d": + func = decode + if o == "-u": + func = decode + if o == "-t": + test() + return + if args and args[0] != "-": + with open(args[0], "rb") as f: + func(f, sys.stdout.buffer) + else: + func(sys.stdin.buffer, sys.stdout.buffer) + + +def test(): + s0 = b"Aladdin:open sesame" + print(repr(s0)) + s1 = encodebytes(s0) + print(repr(s1)) + s2 = decodebytes(s1) + print(repr(s2)) + assert s0 == s2 + + +if __name__ == "__main__": + main() diff --git a/mixly/boards/default/micropython/build/lib/ble_advertising.py b/mixly/boards/default/micropython/build/lib/ble_advertising.py new file mode 100644 index 00000000..b0596f36 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ble_advertising.py @@ -0,0 +1,79 @@ +# Helpers for generating BLE advertising payloads. + +from micropython import const +import struct +import bluetooth + +# Advertising payloads are repeated packets of the following form: +# 1 byte data length (N + 1) +# 1 byte type (see constants below) +# N bytes type-specific data + +_ADV_TYPE_FLAGS = const(0x01) +_ADV_TYPE_NAME = const(0x09) +_ADV_TYPE_UUID16_COMPLETE = const(0x3) +_ADV_TYPE_UUID32_COMPLETE = const(0x5) +_ADV_TYPE_UUID128_COMPLETE = const(0x7) +_ADV_TYPE_UUID16_MORE = const(0x2) +_ADV_TYPE_UUID32_MORE = const(0x4) +_ADV_TYPE_UUID128_MORE = const(0x6) +_ADV_TYPE_APPEARANCE = const(0x19) + + +# Generate a payload to be passed to gap_advertise(adv_data=...). +def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): + payload = bytearray() + + def _append(adv_type, value): + nonlocal payload + payload += struct.pack("BB", len(value) + 1, adv_type) + value + + _append( + _ADV_TYPE_FLAGS, + struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)), + ) + + if name: + _append(_ADV_TYPE_NAME, name.encode()) + + if services: + for uuid in services: + b = bytes(uuid) + if len(b) == 2: + _append(_ADV_TYPE_UUID16_COMPLETE, b) + elif len(b) == 4: + _append(_ADV_TYPE_UUID32_COMPLETE, b) + elif len(b) == 16: + _append(_ADV_TYPE_UUID128_COMPLETE, b) + + # See org.bluetooth.characteristic.gap.appearance.xml + if appearance: + _append(_ADV_TYPE_APPEARANCE, struct.pack(" 5: break + _keys[i] = general[i] + else: + _keys[0] = general + self._ble.gatts_notify(self.conn_handle, self.k_rep, bytes([special & 0xFF, 0]) + _keys) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.k_rep, b'\x00\x00\x00\x00\x00\x00\x00\x00') + + def keyboard_str(self, string, delay=0): + '''键盘发送ASCLL码''' + for char in str(string): + char = max(min(ord(char), 127), 0) + self.keyboard_notify( 0x02 if _KEYCODE[char] >> 7 else 0x00, _KEYCODE[char] & 0x7F) + time.sleep_ms(20 + delay) + + def mouse_notify(self, keys=0, move=(0, 0), wheel=0, release=True): + '''鼠标 按键*3 + 位移 + 滚轮''' + if self.is_connected(): + self._ble.gatts_notify(self.conn_handle, self.m_rep, bytes([keys & 0x0F, move[0] & 0xFF, move[1] & 0xFF, wheel & 0xFF])) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.m_rep, b'\x00\x00\x00\x00') + + def Joystick_notify(self, keys=0, axes=(0, 0), release=False): + '''手柄 按键*8 + 摇杆''' + if self.is_connected(): + self._ble.gatts_notify(self.conn_handle, self.j_rep, bytes([axes[0] & 0xFF, axes[1] & 0xFF, keys & 0xFF])) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.j_rep, b'\x00\x00\x00') + @property + def mac(self): + '''Get mac address''' + return hexlify(self._ble.config('mac')[1]).decode() diff --git a/mixly/boards/default/micropython/build/lib/ble_hid_keyboard.py b/mixly/boards/default/micropython/build/lib/ble_hid_keyboard.py new file mode 100644 index 00000000..4f67ab6a --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ble_hid_keyboard.py @@ -0,0 +1,218 @@ +""" +Bluetooth-HID-Keyboard + +Micropython library for the Bluetooth-HID-Keyboard +======================================================= +#https://github.com/Heerkog/MicroPythonBLEHID + +@dahanzimin From the Mixly Team +""" +import bluetooth +import struct, time +from micropython import const +from ubinascii import hexlify +from ble_advertising import advertising_payload +from bluetooth import UUID, FLAG_READ, FLAG_WRITE ,FLAG_NOTIFY, FLAG_WRITE_NO_RESPONSE + +_IRQ_CENTRAL_CONNECT = const(1) +_IRQ_CENTRAL_DISCONNECT = const(2) +_IRQ_GATTS_WRITE = const(3) +_IRQ_MTU_EXCHANGED = const(21) +_IRQ_CONNECTION_UPDATE = const(27) +_IRQ_GET_SECRET = const(29) +_IRQ_SET_SECRET = const(30) +_IRQ_PASSKEY_ACTION = const(31) +_PASSKEY_ACTION_INPUT = const(2) +_PASSKEY_ACTION_DISP = const(3) +_PASSKEY_ACTION_NUMCMP = const(4) + +_HID_INPUT_REPORT = const(b'\x05\x01\t\x06\xa1\x01\x85\x01u\x01\x95\x08\x05\x07\x19\xe0)\xe7\x15\x00%\x01\x81\x02\x95\x01u\x08\x81\x01\x95\x05u\x01\x05\x08\x19\x01)\x05\x91\x02\x95\x01u\x03\x91\x01\x95\x06u\x08\x15\x00%e\x05\x07\x19\x00)e\x81\x00\xc0') +_KEYCODE = const(b'\x00\x00\x00\x00\x00\x00\x00\x00*+(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x00,\x9e\xb4\xa0\xa1\xa2\xa44\xa6\xa7\xa5\xae6-78\'\x1e\x1f !"#$%&\xb33\xb6.\xb7\xb8\x9f\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d/10\xa3\xad5\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\xaf\xb1\xb0\xb5L') + +_DIS = (UUID(0x180A), ( (UUID(0x2A24), FLAG_READ), + (UUID(0x2A25), FLAG_READ), + (UUID(0x2A26), FLAG_READ), + (UUID(0x2A27), FLAG_READ), + (UUID(0x2A28), FLAG_READ), + (UUID(0x2A29), FLAG_READ), + (UUID(0x2A50), FLAG_READ), ), ) + +_BAS = (UUID(0x180F), ( (UUID(0x2A19), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2904), 0x01),)), ), ) + +_HIDS = (UUID(0x1812), ((UUID(0x2A4A), FLAG_READ), + (UUID(0x2A4B), FLAG_READ), + (UUID(0x2A4C), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), + (UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2908), 0x01 | 0x02),)), + (UUID(0x2A4D), FLAG_READ | FLAG_WRITE, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2908), 0x01 | 0x02),)), + (UUID(0x2A4E), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), ), ) + +class Keyboard: + def __init__(self, name=None, passkey=1234, battery_level=100): + if (name is '') or (name is None): + name = "Mixgo_" + self.mac[-6:].upper() + print("Keyboard name:", name) + + self._ble = bluetooth.BLE() + self._ble.active(True) + self._ble.irq(self._irq) + self._ble.config(gap_name=name) + self._ble.config(mtu=23) + self.device_state = False + self.conn_handle = None + self.passkey = passkey + self.battery_level = battery_level + self.report = b'\x00' + try: + import ble_hid_key + self.keys = ble_hid_key.keys + except: + self.keys = {} + + handles = self._ble.gatts_register_services((_DIS, _BAS, _HIDS)) + self._service_characteristics(handles) + self._payload = advertising_payload(name=name, services=[UUID(0x1812)], appearance=const(961)) + self.advertise() + + def _irq(self, event, data): + # Interrupt request callback function + if event == _IRQ_CENTRAL_CONNECT: + self.conn_handle, _, _ = data + print("Keyboard connected: ", self.conn_handle) + self.device_state = True + elif event == _IRQ_CENTRAL_DISCONNECT: + self.conn_handle = None + conn_handle, addr_type, addr = data + print("Keyboard disconnected: ", conn_handle) + self.advertise() + self.device_state = False + elif event == _IRQ_MTU_EXCHANGED: + conn_handle, mtu = data + self._ble.config(mtu=mtu) + print("MTU exchanged: ", mtu) + elif event == _IRQ_CONNECTION_UPDATE: + self.conn_handle, _, _, _, _ = data + print("Connection update") + elif event == _IRQ_PASSKEY_ACTION: + conn_handle, action, passkey = data + print("Passkey action", conn_handle, action, passkey) + if action == _PASSKEY_ACTION_NUMCMP: + self._ble.gap_passkey(conn_handle, action, False) + elif action == _PASSKEY_ACTION_DISP: + print("Displaying passkey") + self._ble.gap_passkey(conn_handle, action, self.passkey) + elif action == _PASSKEY_ACTION_INPUT: + print(" Prompting for passkey") + self._ble.gap_passkey(conn_handle, action, None) + else: + print("unknown action") + elif event == _IRQ_GATTS_WRITE: + conn_handle, attr_handle = data + self.report = self._ble.gatts_read(attr_handle) + elif event == _IRQ_SET_SECRET: + sec_type, key, value = data + key = sec_type, bytes(key) + value = bytes(value) if value else None + #print("Set secret: ", key, value) + if value is None: + if key in self.keys: + del self.keys[key] + self.key_secrets(self.keys) + return True + else: + return False + else: + self.keys[key] = value + self.key_secrets(self.keys) + return True + elif event == _IRQ_GET_SECRET: + sec_type, index, key = data + #print("Get secret: ", sec_type, index, bytes(key) if key else None) + if key is None: + i = 0 + for (t, _key), value in self.keys.items(): + if t == sec_type: + if i == index: + return value + i += 1 + return None + else: + key = sec_type, bytes(key) + return self.keys.get(key, None) + #else: + #print("Unhandled IRQ event: ", event, data) + + def key_secrets(self, keys={}): + with open("ble_hid_key.py", "w+") as s_f: + s_f.write("keys=" + str(keys) + "\n") + + def _service_characteristics(self, handles): + (h_mod, h_ser, h_fwr, h_hwr, h_swr, h_man, h_pnp) = handles[0] + (self.h_bat, h_ccc, h_bfmt,) = handles[1] + (h_info, h_hid, _, self.h_rep, _, h_d1, _, _, h_d2, h_proto) = handles[2] + + # Write DIS characteristics. + self._ble.gatts_write(h_mod, b'1') + self._ble.gatts_write(h_ser, b'1') + self._ble.gatts_write(h_fwr, b'1') + self._ble.gatts_write(h_hwr, b'1') + self._ble.gatts_write(h_swr, b'1') + self._ble.gatts_write(h_man, b'Homebrew') + self._ble.gatts_write(h_pnp, struct.pack(" 5: break + _keys[i] = general[i] + else: + _keys[0] = general + # Pack the mouse state as described by the input report + self._ble.gatts_notify(self.conn_handle, self.h_rep, bytes([special & 0xFF, 0]) + _keys) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.h_rep, b'\x00\x00\x00\x00\x00\x00\x00\x00') + + def notify_battery(self, level): + if self.is_connected(): + self.battery_level = max(min(level, 100), 0) + # Notifies the client by writing to the battery level handle. + self._ble.gatts_notify(self.conn_handle, self.h_bat, struct.pack("> 7 else 0x00, _KEYCODE[char] & 0x7F) + time.sleep_ms(20 + delay) + + @property + def mac(self): + '''Get mac address''' + return hexlify(self._ble.config('mac')[1]).decode() diff --git a/mixly/boards/default/micropython/build/lib/ble_hid_mouse.py b/mixly/boards/default/micropython/build/lib/ble_hid_mouse.py new file mode 100644 index 00000000..9f0fef69 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ble_hid_mouse.py @@ -0,0 +1,193 @@ +""" +Bluetooth-HID-Mouse + +Micropython library for the Bluetooth-HID-Mouse +======================================================= +#https://github.com/Heerkog/MicroPythonBLEHID + +@dahanzimin From the Mixly Team +""" +import bluetooth +import struct, time +from micropython import const +from ubinascii import hexlify +from ble_advertising import advertising_payload +from bluetooth import UUID, FLAG_READ, FLAG_WRITE ,FLAG_NOTIFY, FLAG_WRITE_NO_RESPONSE + +_IRQ_CENTRAL_CONNECT = const(1) +_IRQ_CENTRAL_DISCONNECT = const(2) +_IRQ_MTU_EXCHANGED = const(21) +_IRQ_CONNECTION_UPDATE = const(27) +_IRQ_GET_SECRET = const(29) +_IRQ_SET_SECRET = const(30) +_IRQ_PASSKEY_ACTION = const(31) +_PASSKEY_ACTION_INPUT = const(2) +_PASSKEY_ACTION_DISP = const(3) +_PASSKEY_ACTION_NUMCMP = const(4) + +_HID_INPUT_REPORT = const(b'\x05\x01\t\x02\xa1\x01\x85\x01\t\x01\xa1\x00\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x03\x05\x01\t0\t1\t8\x15\x81%\x7fu\x08\x95\x03\x81\x06\xc0\xc0') + +_DIS = (UUID(0x180A), ( (UUID(0x2A24), FLAG_READ), + (UUID(0x2A25), FLAG_READ), + (UUID(0x2A26), FLAG_READ), + (UUID(0x2A27), FLAG_READ), + (UUID(0x2A28), FLAG_READ), + (UUID(0x2A29), FLAG_READ), + (UUID(0x2A50), FLAG_READ), ), ) + +_BAS = (UUID(0x180F), ( (UUID(0x2A19), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2904), 0x01),)), ), ) + +_HIDS = (UUID(0x1812), ((UUID(0x2A4A), FLAG_READ), + (UUID(0x2A4B), FLAG_READ), + (UUID(0x2A4C), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), + (UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2908), 0x01 | 0x02), )), + (UUID(0x2A4E), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), ), ) + +class Mouse: + def __init__(self, name=None, passkey=1234, battery_level=100): + if (name is '') or (name is None): + name = "Mixgo_" + self.mac[-6:].upper() + print("Mouse name:", name) + + self._ble = bluetooth.BLE() + self._ble.active(True) + self._ble.irq(self._irq) + self._ble.config(gap_name=name) + self._ble.config(mtu=23) + self.device_state = False + self.conn_handle = None + self.passkey = passkey + self.battery_level = battery_level + try: + import ble_hid_key + self.keys = ble_hid_key.keys + except: + self.keys = {} + + handles = self._ble.gatts_register_services((_DIS, _BAS, _HIDS)) + self._service_characteristics(handles) + self._payload = advertising_payload(name=name, services=[UUID(0x1812)], appearance=const(962)) + self.advertise() + + def _irq(self, event, data): + # Interrupt request callback function + if event == _IRQ_CENTRAL_CONNECT: + self.conn_handle, _, _ = data + print("Mouse connected: ", self.conn_handle) + self.device_state = True + elif event == _IRQ_CENTRAL_DISCONNECT: + self.conn_handle = None + conn_handle, addr_type, addr = data + print("Mouse disconnected: ", conn_handle) + self.advertise() + self.device_state = False + elif event == _IRQ_MTU_EXCHANGED: + conn_handle, mtu = data + self._ble.config(mtu=mtu) + print("MTU exchanged: ", mtu) + elif event == _IRQ_CONNECTION_UPDATE: + self.conn_handle, _, _, _, _ = data + print("Connection update") + elif event == _IRQ_PASSKEY_ACTION: + conn_handle, action, passkey = data + print("Passkey action", conn_handle, action, passkey) + if action == _PASSKEY_ACTION_NUMCMP: + self._ble.gap_passkey(conn_handle, action, False) + elif action == _PASSKEY_ACTION_DISP: + print("Displaying passkey") + self._ble.gap_passkey(conn_handle, action, self.passkey) + elif action == _PASSKEY_ACTION_INPUT: + print(" Prompting for passkey") + self._ble.gap_passkey(conn_handle, action, None) + else: + print("unknown action") + elif event == _IRQ_SET_SECRET: + sec_type, key, value = data + key = sec_type, bytes(key) + value = bytes(value) if value else None + #print("Set secret: ", key, value) + if value is None: + if key in self.keys: + del self.keys[key] + self.key_secrets(self.keys) + return True + else: + return False + else: + self.keys[key] = value + self.key_secrets(self.keys) + return True + elif event == _IRQ_GET_SECRET: + sec_type, index, key = data + #print("Get secret: ", sec_type, index, bytes(key) if key else None) + if key is None: + i = 0 + for (t, _key), value in self.keys.items(): + if t == sec_type: + if i == index: + return value + i += 1 + return None + else: + key = sec_type, bytes(key) + return self.keys.get(key, None) + #else: + #print("Unhandled IRQ event: ", event, data) + + def key_secrets(self, keys={}): + with open("ble_hid_key.py", "w+") as s_f: + s_f.write("keys=" + str(keys) + "\n") + + def _service_characteristics(self, handles): + (h_mod, h_ser, h_fwr, h_hwr, h_swr, h_man, h_pnp) = handles[0] + (self.h_bat, h_ccc, h_bfmt,) = handles[1] + (h_info, h_hid, h_ctrl, self.h_rep, _, h_d1, h_proto) = handles[2] + + # Write DIS characteristics. + self._ble.gatts_write(h_mod, b'1') + self._ble.gatts_write(h_ser, b'1') + self._ble.gatts_write(h_fwr, b'1') + self._ble.gatts_write(h_hwr, b'1') + self._ble.gatts_write(h_swr, b'1') + self._ble.gatts_write(h_man, b'Homebrew') + self._ble.gatts_write(h_pnp, struct.pack(" 0 + + def _advertise(self, interval_us=500000): + print("Starting advertising") + self._ble.gap_advertise(interval_us, adv_data=self._payload) + + def recv(self, callback= None): + if callback: + self._write_callback = callback + else: + write_data=self._write_data + self._write_data=None + return write_data + + @property + def mac(self): + '''Get mac address''' + return hexlify(self._ble.config('mac')[1]).decode() diff --git a/mixly/boards/default/micropython/build/lib/ble_uart_peripheral.py b/mixly/boards/default/micropython/build/lib/ble_uart_peripheral.py new file mode 100644 index 00000000..3009a663 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ble_uart_peripheral.py @@ -0,0 +1,86 @@ +""" +Bluetooth-uart-Peripheral + +Micropython library for the Bluetooth-uart-Peripheral +======================================================= +#Preliminary composition 202200628 +#https://github.com/micropython/micropython/tree/master/examples/bluetooth + +dahanzimin From the Mixly Team +""" + +import bluetooth +from ble_advertising import advertising_payload +from micropython import const + +_IRQ_CENTRAL_CONNECT = const(1) +_IRQ_CENTRAL_DISCONNECT = const(2) +_IRQ_GATTS_WRITE = const(3) + +_FLAG_READ = const(0x0002) +_FLAG_WRITE_NO_RESPONSE = const(0x0004) +_FLAG_WRITE = const(0x0008) +_FLAG_NOTIFY = const(0x0010) + +_UART_UUID = bluetooth.UUID("0000fff0-0000-1000-8000-00805f9b34fb") +_UART_TX = (bluetooth.UUID("0000fff1-0000-1000-8000-00805f9b34fb"),_FLAG_READ | _FLAG_NOTIFY,) +_UART_RX = (bluetooth.UUID("0000fff2-0000-1000-8000-00805f9b34fb"),_FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,) +_UART_SERVICE = (_UART_UUID,(_UART_TX, _UART_RX),) + +class BLEUART: + def __init__(self, name="mpy-uart", rxbuf=100): + self._ble = bluetooth.BLE() + self._ble.active(True) + self._ble.irq(self._irq) + ((self._tx_handle, self._rx_handle),) = self._ble.gatts_register_services((_UART_SERVICE,)) + self._ble.gatts_set_buffer(self._rx_handle, rxbuf, True) + self._connections = set() + self._rx_buffer = bytearray() + self._handler = None + self._payload = advertising_payload(name=name, services=[_UART_UUID]) + self._advertise() + + def irq(self, handler): + self._handler = handler + + def _irq(self, event, data): + # Track connections so we can send notifications. + if event == _IRQ_CENTRAL_CONNECT: + conn_handle, _, _ = data + print("Bluetooth connected") + self._connections.add(conn_handle) + elif event == _IRQ_CENTRAL_DISCONNECT: + conn_handle, _, _ = data + print("Bluetooth disconnected") + if conn_handle in self._connections: + self._connections.remove(conn_handle) + # Start advertising again to allow a new connection. + self._advertise() + elif event == _IRQ_GATTS_WRITE: + conn_handle, value_handle = data + if conn_handle in self._connections and value_handle == self._rx_handle: + self._rx_buffer += self._ble.gatts_read(self._rx_handle) + if self._handler: + self._handler() + + def any(self): + return len(self._rx_buffer) + + def read(self, sz=None): + if not sz: + sz = len(self._rx_buffer) + result = self._rx_buffer[0:sz] + self._rx_buffer = self._rx_buffer[sz:] + return result + + def write(self, data): + for conn_handle in self._connections: + self._ble.gatts_notify(conn_handle, self._tx_handle, data) + + def close(self): + for conn_handle in self._connections: + self._ble.gap_disconnect(conn_handle) + self._connections.clear() + + def _advertise(self, interval_us=500000): + self._ble.gap_advertise(interval_us, adv_data=self._payload) diff --git a/mixly/boards/default/micropython/build/lib/ble_uart_repl.py b/mixly/boards/default/micropython/build/lib/ble_uart_repl.py new file mode 100644 index 00000000..f88d99ab --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ble_uart_repl.py @@ -0,0 +1,67 @@ +# Proof-of-concept of a REPL over BLE UART. +# Set the EoL characters to \r\n. + +import io +import os +from machine import Timer +from micropython import schedule +from ble_uart_peripheral import BLEUART + +_MP_STREAM_POLL = const(3) +_MP_STREAM_POLL_RD = const(0x0001) + +# Batch writes into 50ms intervals. +Define_timer = Timer(2) + +def schedule_in(handler, delay_ms): + def _wrap(_arg): + handler() + if Define_timer: + Define_timer.init(mode=Timer.ONE_SHOT, period=delay_ms, callback=_wrap) + else: + schedule(_wrap, None) + +# Simple buffering stream to support the dupterm requirements. +class BLEUARTStream(io.IOBase): + def __init__(self, name="mpy-repl"): + self._uart = BLEUART(name) + self._tx_buf = bytearray() + self._uart.irq(self._on_rx) + + def _on_rx(self): + if hasattr(os, "dupterm_notify"): + os.dupterm_notify(None) + + def read(self, sz=None): + return self._uart.read(sz) + + def readinto(self, buf): + avail = self._uart.read(len(buf)) + if not avail: + return None + for i in range(len(avail)): + buf[i] = avail[i] + return len(avail) + + def ioctl(self, op, arg): + if op == _MP_STREAM_POLL: + if self._uart.any(): + return _MP_STREAM_POLL_RD + return 0 + + def _flush(self): + data = self._tx_buf[0:100] + self._tx_buf = self._tx_buf[100:] + self._uart.write(data) + if self._tx_buf: + schedule_in(self._flush, 50) + + def write(self, buf): + empty = not self._tx_buf + self._tx_buf += buf + if empty: + schedule_in(self._flush, 50) + +def start(ble_name="mpy-repl"): + stream = BLEUARTStream(name=ble_name) + os.dupterm(stream) diff --git a/mixly/boards/default/micropython/build/lib/blynklib.py b/mixly/boards/default/micropython/build/lib/blynklib.py new file mode 100644 index 00000000..46f88977 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/blynklib.py @@ -0,0 +1,377 @@ +# Copyright (c) 2019-2020 Anton Morozenko +# Copyright (c) 2015-2019 Volodymyr Shymanskyy. +# See the file LICENSE for copying permission. + +__version__ = '0.2.6' + +import usocket as socket +import utime as time +import ustruct as struct +import uselect as select +from micropython import const + +ticks_ms = time.ticks_ms +sleep_ms = time.sleep_ms + +IOError = OSError + +LOGO = """ + ___ __ __ + / _ )/ /_ _____ / /__ + / _ / / // / _ \\/ '_/ + /____/_/\\_, /_//_/_/\\_\\ + /___/ for Python v{}\n""".format(__version__) + + +def stub_log(*args): + pass + + +class BlynkError(Exception): + pass + + +class RedirectError(Exception): + def __init__(self, server, port): + self.server = server + self.port = port + + +class Protocol(object): + MSG_RSP = const(0) + MSG_LOGIN = const(2) + MSG_PING = const(6) + MSG_TWEET = const(12) + MSG_EMAIL = const(13) + MSG_NOTIFY = const(14) + MSG_BRIDGE = const(15) + MSG_HW_SYNC = const(16) + MSG_INTERNAL = const(17) + MSG_PROPERTY = const(19) + MSG_HW = const(20) + MSG_REDIRECT = const(41) + MSG_HEAD_LEN = const(5) + + STATUS_INVALID_TOKEN = const(9) + STATUS_OK = const(200) + VPIN_MAX_NUM = const(32) + + _msg_id = 1 + + def _get_msg_id(self, **kwargs): + if 'msg_id' in kwargs: + return kwargs['msg_id'] + self._msg_id += const(1) + return self._msg_id if self._msg_id <= const(0xFFFF) else const(1) + + def _pack_msg(self, msg_type, *args, **kwargs): + data = ('\0'.join([str(curr_arg) for curr_arg in args])).encode('utf-8') + return struct.pack('!BHH', msg_type, self._get_msg_id(**kwargs), len(data)) + data + + def parse_response(self, rsp_data, msg_buffer): + msg_args = [] + msg_len = 0 + try: + msg_type, msg_id, h_data = struct.unpack('!BHH', rsp_data[:self.MSG_HEAD_LEN]) + msg_len = self.MSG_HEAD_LEN + h_data + except Exception as p_err: + raise BlynkError('Message parse error: {}'.format(p_err)) + if msg_id == 0: + raise BlynkError('invalid msg_id == 0') + elif h_data >= msg_buffer: + raise BlynkError('Command too long. Length = {}'.format(h_data)) + elif msg_type in (self.MSG_RSP, self.MSG_PING): + pass + elif msg_type in (self.MSG_HW, self.MSG_BRIDGE, self.MSG_INTERNAL, self.MSG_REDIRECT): + msg_body = rsp_data[self.MSG_HEAD_LEN: msg_len] + msg_args = [itm.decode('utf-8') for itm in msg_body.split(b'\0')] + else: + raise BlynkError("Unknown message type: '{}'".format(msg_type)) + return msg_type, msg_id, h_data, msg_args, msg_len + + def heartbeat_msg(self, heartbeat, rcv_buffer): + return self._pack_msg(self.MSG_INTERNAL, 'ver', __version__, 'buff-in', rcv_buffer, 'h-beat', heartbeat, + 'dev', 'mpython') + + def login_msg(self, token): + return self._pack_msg(self.MSG_LOGIN, token) + + def ping_msg(self): + return self._pack_msg(self.MSG_PING) + + def response_msg(self, *args, **kwargs): + return self._pack_msg(self.MSG_RSP, *args, **kwargs) + + def virtual_write_msg(self, v_pin, *val): + return self._pack_msg(self.MSG_HW, 'vw', v_pin, *val) + + def virtual_sync_msg(self, *pins): + return self._pack_msg(self.MSG_HW_SYNC, 'vr', *pins) + + def email_msg(self, to, subject, body): + return self._pack_msg(self.MSG_EMAIL, to, subject, body) + + def tweet_msg(self, msg): + return self._pack_msg(self.MSG_TWEET, msg) + + def notify_msg(self, msg): + return self._pack_msg(self.MSG_NOTIFY, msg) + + def set_property_msg(self, pin, prop, *val): + return self._pack_msg(self.MSG_PROPERTY, pin, prop, *val) + + def internal_msg(self, *args): + return self._pack_msg(self.MSG_INTERNAL, *args) + + +class Connection(Protocol): + SOCK_MAX_TIMEOUT = const(5) + SOCK_TIMEOUT = 0.05 + EAGAIN = const(11) + ETIMEDOUT = const(60) + RETRIES_TX_DELAY = const(2) + RETRIES_TX_MAX_NUM = const(3) + RECONNECT_SLEEP = const(1) + TASK_PERIOD_RES = const(50) + DISCONNECTED = const(0) + CONNECTING = const(1) + AUTHENTICATING = const(2) + AUTHENTICATED = const(3) + + _state = None + _socket = None + _last_rcv_time = 0 + _last_ping_time = 0 + _last_send_time = 0 + + def __init__(self, token, server='blynk-cloud.com', port=80, heartbeat=10, rcv_buffer=1024, log=stub_log): + self.token = token + self.server = server + self.port = port + self.heartbeat = heartbeat + self.rcv_buffer = rcv_buffer + self.log = log + + def _set_socket_timeout(self, timeout): + if getattr(self._socket, 'settimeout', None): + self._socket.settimeout(timeout) + else: + p = select.poll() + p.register(self._socket) + p.poll(int(timeout * const(1000))) + + def send(self, data): + retries = self.RETRIES_TX_MAX_NUM + while retries > 0: + try: + retries -= 1 + self._last_send_time = ticks_ms() + return self._socket.send(data) + except (IOError, OSError): + sleep_ms(self.RETRIES_TX_DELAY) + + def receive(self, length, timeout): + d_buff = b'' + try: + self._set_socket_timeout(timeout) + d_buff += self._socket.recv(length) + if len(d_buff) >= length: + d_buff = d_buff[:length] + return d_buff + except (IOError, OSError) as err: + if str(err) == 'timed out': + return b'' + if str(self.EAGAIN) in str(err) or str(self.ETIMEDOUT) in str(err): + return b'' + raise + + def is_server_alive(self): + now = ticks_ms() + h_beat_ms = self.heartbeat * const(1000) + rcv_delta = time.ticks_diff(now, self._last_rcv_time) + ping_delta = time.ticks_diff(now, self._last_ping_time) + send_delta = time.ticks_diff(now, self._last_send_time) + if rcv_delta > h_beat_ms + (h_beat_ms // const(2)): + return False + if (ping_delta > h_beat_ms // const(10)) and (send_delta > h_beat_ms or rcv_delta > h_beat_ms): + self.send(self.ping_msg()) + self.log('Heartbeat time: {}'.format(now)) + self._last_ping_time = now + return True + + def _get_socket(self): + try: + self._state = self.CONNECTING + self._socket = socket.socket() + self._socket.connect(socket.getaddrinfo(self.server, self.port)[0][-1]) + self._set_socket_timeout(self.SOCK_TIMEOUT) + self.log('Connected to server') + except Exception as g_exc: + raise BlynkError('Server connection failed: {}'.format(g_exc)) + + def _authenticate(self): + self.log('Authenticating device...') + self._state = self.AUTHENTICATING + self.send(self.login_msg(self.token)) + rsp_data = self.receive(self.rcv_buffer, self.SOCK_MAX_TIMEOUT) + if not rsp_data: + raise BlynkError('Auth stage timeout') + msg_type, _, status, args, _ = self.parse_response(rsp_data, self.rcv_buffer) + if status != self.STATUS_OK: + if status == self.STATUS_INVALID_TOKEN: + raise BlynkError('Invalid Auth Token') + if msg_type == self.MSG_REDIRECT: + raise RedirectError(*args) + raise BlynkError('Auth stage failed. Status={}'.format(status)) + self._state = self.AUTHENTICATED + self.log('Access granted') + + def _set_heartbeat(self): + self.send(self.heartbeat_msg(self.heartbeat, self.rcv_buffer)) + rcv_data = self.receive(self.rcv_buffer, self.SOCK_MAX_TIMEOUT) + if not rcv_data: + raise BlynkError('Heartbeat stage timeout') + _, _, status, _, _ = self.parse_response(rcv_data, self.rcv_buffer) + if status != self.STATUS_OK: + raise BlynkError('Set heartbeat returned code={}'.format(status)) + self.log('Heartbeat = {} sec. MaxCmdBuffer = {} bytes'.format(self.heartbeat, self.rcv_buffer)) + + def connected(self): + return True if self._state == self.AUTHENTICATED else False + + +class Blynk(Connection): + _CONNECT_TIMEOUT = const(30) # 30sec + _VPIN_WILDCARD = '*' + _VPIN_READ = 'read v' + _VPIN_WRITE = 'write v' + _INTERNAL = 'internal_' + _CONNECT = 'connect' + _DISCONNECT = 'disconnect' + _VPIN_READ_ALL = '{}{}'.format(_VPIN_READ, _VPIN_WILDCARD) + _VPIN_WRITE_ALL = '{}{}'.format(_VPIN_WRITE, _VPIN_WILDCARD) + _events = {} + + def __init__(self, token, **kwargs): + Connection.__init__(self, token, **kwargs) + self._start_time = ticks_ms() + self._last_rcv_time = ticks_ms() + self._last_send_time = ticks_ms() + self._last_ping_time = ticks_ms() + self._state = self.DISCONNECTED + print(LOGO) + + def connect(self, timeout=_CONNECT_TIMEOUT): + end_time = time.time() + timeout + while not self.connected(): + if self._state == self.DISCONNECTED: + try: + self._get_socket() + self._authenticate() + self._set_heartbeat() + self._last_rcv_time = ticks_ms() + self.log('Registered events: {}\n'.format(list(self._events.keys()))) + self.call_handler(self._CONNECT) + return True + except BlynkError as b_err: + self.disconnect(b_err) + sleep_ms(self.TASK_PERIOD_RES) + except RedirectError as r_err: + self.disconnect() + self.server = r_err.server + self.port = r_err.port + sleep_ms(self.TASK_PERIOD_RES) + if time.time() >= end_time: + return False + + def disconnect(self, err_msg=None): + self.call_handler(self._DISCONNECT) + if self._socket: + self._socket.close() + self._state = self.DISCONNECTED + if err_msg: + self.log('[ERROR]: {}\nConnection closed'.format(err_msg)) + time.sleep(self.RECONNECT_SLEEP) + + def virtual_write(self, v_pin, *val): + return self.send(self.virtual_write_msg(v_pin, *val)) + + def virtual_sync(self, *v_pin): + return self.send(self.virtual_sync_msg(*v_pin)) + + def email(self, to, subject, body): + return self.send(self.email_msg(to, subject, body)) + + def tweet(self, msg): + return self.send(self.tweet_msg(msg)) + + def notify(self, msg): + return self.send(self.notify_msg(msg)) + + def set_property(self, v_pin, property_name, *val): + return self.send(self.set_property_msg(v_pin, property_name, *val)) + + def internal(self, *args): + return self.send(self.internal_msg(*args)) + + def handle_event(blynk, event_name): + class Deco(object): + def __init__(self, func): + self.func = func + # wildcard 'read V*' and 'write V*' events handling + if str(event_name).lower() in (blynk._VPIN_READ_ALL, blynk._VPIN_WRITE_ALL): + event_base_name = str(event_name).split(blynk._VPIN_WILDCARD)[0] + for i in range(blynk.VPIN_MAX_NUM + 1): + blynk._events['{}{}'.format(event_base_name.lower(), i)] = func + else: + blynk._events[str(event_name).lower()] = func + + def __call__(self): + return self.func() + + return Deco + + def call_handler(self, event, *args, **kwargs): + if event in self._events.keys(): + self.log("Event: ['{}'] -> {}".format(event, args)) + self._events[event](*args, **kwargs) + + def process(self, msg_type, msg_id, msg_len, msg_args): + if msg_type == self.MSG_RSP: + self.log('Response status: {}'.format(msg_len)) + elif msg_type == self.MSG_PING: + self.send(self.response_msg(self.STATUS_OK, msg_id=msg_id)) + elif msg_type in (self.MSG_HW, self.MSG_BRIDGE, self.MSG_INTERNAL): + if msg_type == self.MSG_INTERNAL: + self.call_handler("{}{}".format(self._INTERNAL, msg_args[0]), msg_args[1:]) + elif len(msg_args) >= const(3) and msg_args[0] == 'vw': + self.call_handler("{}{}".format(self._VPIN_WRITE, msg_args[1]), int(msg_args[1]), msg_args[2:]) + elif len(msg_args) == const(2) and msg_args[0] == 'vr': + self.call_handler("{}{}".format(self._VPIN_READ, msg_args[1]), int(msg_args[1])) + + def read_response(self, timeout=0.5): + end_time = time.ticks_ms() + int(timeout * const(1000)) + while time.ticks_diff(end_time, time.ticks_ms()) > 0: + rsp_data = self.receive(self.rcv_buffer, self.SOCK_TIMEOUT) + if rsp_data: + self._last_rcv_time = ticks_ms() + while rsp_data: + msg_type, msg_id, h_data, msg_args, msg_len = self.parse_response(rsp_data, self.rcv_buffer) + self.process(msg_type, msg_id, h_data, msg_args) + rsp_data = rsp_data[msg_len:] + + def run(self): + if not self.connected(): + self.connect() + else: + try: + self.read_response(timeout=self.SOCK_TIMEOUT) + if not self.is_server_alive(): + self.disconnect('Server is offline') + except KeyboardInterrupt: + raise + except BlynkError as b_err: + self.log(b_err) + self.disconnect() + except Exception as g_exc: + self.log(g_exc) diff --git a/mixly/boards/default/micropython/build/lib/blynktimer.py b/mixly/boards/default/micropython/build/lib/blynktimer.py new file mode 100644 index 00000000..704a3911 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/blynktimer.py @@ -0,0 +1,133 @@ +# Copyright (c) 2019-2020 Anton Morozenko +""" +Polling timers for functions. +Registers timers and performs run once or periodical function execution after defined time intervals. +""" +# select.select call used as polling waiter where it is possible +# cause time.sleep sometimes may load CPU up to 100% with small polling wait interval +try: + # cpython + import time + import select + + polling_wait = lambda x: select.select([], [], [], x) + polling_wait(0.01) +except OSError: + # windows case where select.select call fails + polling_wait = lambda x: time.sleep(x) + +except ImportError: + # micropython + import utime as time + + try: + from uselect import select as s_select + + polling_wait = lambda x: s_select([], [], [], x) + except ImportError: + # case when micropython port does not support select.select + polling_wait = lambda x: time.sleep(x) + +WAIT_SEC = 0.05 +MAX_TIMERS = 16 +DEFAULT_INTERVAL = 10 + + +class TimerError(Exception): + pass + + +class Timer(object): + timers = {} + + def __init__(self, no_timers_err=True): + self.no_timers_err = no_timers_err + + def _get_func_name(self, obj): + """retrieves a suitable name for a function""" + if hasattr(obj, 'func'): + # handles nested decorators + return self._get_func_name(obj.func) + # simply returns 'timer' if on port without function attrs + return getattr(obj, '__name__', 'timer') + + def register(blynk, *args, **kwargs): + # kwargs with defaults are used cause PEP 3102 no supported by Python2 + interval = kwargs.pop('interval', DEFAULT_INTERVAL) + run_once = kwargs.pop('run_once', False) + stopped = kwargs.pop('stopped', False) + + class Deco(object): + def __init__(self, func): + self.func = func + if len(list(Timer.timers.keys())) >= MAX_TIMERS: + raise TimerError('Max allowed timers num={}'.format(MAX_TIMERS)) + _timer = _Timer(interval, func, run_once, stopped, *args, **kwargs) + Timer.timers['{}_{}'.format(len(list(Timer.timers.keys())), blynk._get_func_name(func))] = _timer + + def __call__(self, *f_args, **f_kwargs): + return self.func(*f_args, **f_kwargs) + + return Deco + + @staticmethod + def stop(t_id): + timer = Timer.timers.get(t_id, None) + if timer is None: + raise TimerError('Timer id={} not found'.format(t_id)) + Timer.timers[t_id].stopped = True + + @staticmethod + def start(t_id): + timer = Timer.timers.get(t_id, None) + if timer is None: + raise TimerError('Timer id={} not found'.format(t_id)) + Timer.timers[t_id].stopped = False + Timer.timers[t_id].fire_time = None + Timer.timers[t_id].fire_time_prev = None + + @staticmethod + def is_stopped(t_id): + timer = Timer.timers.get(t_id, None) + if timer is None: + raise TimerError('Timer id={} not found'.format(t_id)) + return timer.stopped + + def get_timers(self): + states = {True: 'Stopped', False: 'Running'} + return {k: states[v.stopped] for k, v in self.timers.items()} + + def run(self): + polling_wait(WAIT_SEC) + timers_intervals = [curr_timer.run() for curr_timer in Timer.timers.values() if not curr_timer.stopped] + if not timers_intervals and self.no_timers_err: + raise TimerError('Running timers not found') + return timers_intervals + + +class _Timer(object): + def __init__(self, interval, deco, run_once, stopped, *args, **kwargs): + self.interval = interval + self.deco = deco + self.args = args + self.run_once = run_once + self.kwargs = kwargs + self.fire_time = None + self.fire_time_prev = None + self.stopped = stopped + + def run(self): + timer_real_interval = 0 + if self.fire_time is None: + self.fire_time = time.time() + self.interval + if self.fire_time_prev is None: + self.fire_time_prev = time.time() + curr_time = time.time() + if curr_time >= self.fire_time: + self.deco(*self.args, **self.kwargs) + if self.run_once: + self.stopped = True + timer_real_interval = curr_time - self.fire_time_prev + self.fire_time_prev = self.fire_time + self.fire_time = curr_time + self.interval + return timer_real_interval diff --git a/mixly/boards/default/micropython/build/lib/bmp280.py b/mixly/boards/default/micropython/build/lib/bmp280.py new file mode 100644 index 00000000..02d2cbd5 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/bmp280.py @@ -0,0 +1,162 @@ +from ustruct import unpack as unp +import utime + +# Power Modes +NORMAL = 0 +BMP280_TEMP_OS_SKIP = 0 +BMP280_TEMP_OS_1 = 1 +BMP280_TEMP_OS_2 = 2 +BMP280_TEMP_OS_4 = 3 +BMP280_TEMP_OS_8 = 4 +BMP280_TEMP_OS_16 = 5 +BMP280_PRES_OS_SKIP = 0 +BMP280_PRES_OS_1 = 1 +BMP280_PRES_OS_2 = 2 +BMP280_PRES_OS_4 = 3 +BMP280_PRES_OS_8 = 4 +BMP280_PRES_OS_16 = 5 +# BMP280 Temperature Registers +BMP280_REGISTER_DIG_T1 = 0x88 +BMP280_REGISTER_DIG_T2 = 0x8A +BMP280_REGISTER_DIG_T3 = 0x8C +# BMP280 Pressure Registers +BMP280_REGISTER_DIG_P1 = 0x8E +BMP280_REGISTER_DIG_P2 = 0x90 +BMP280_REGISTER_DIG_P3 = 0x92 +BMP280_REGISTER_DIG_P4 = 0x94 +BMP280_REGISTER_DIG_P5 = 0x96 +BMP280_REGISTER_DIG_P6 = 0x98 +BMP280_REGISTER_DIG_P7 = 0x9A +BMP280_REGISTER_DIG_P8 = 0x9C +BMP280_REGISTER_DIG_P9 = 0x9E +BMP280_REGISTER_ID = 0xD0 +BMP280_REGISTER_RESET = 0xE0 +BMP280_REGISTER_STATUS = 0xF3 +BMP280_REGISTER_CONTROL = 0xF4 +BMP280_REGISTER_CONFIG = 0xF5 # IIR filter config +BMP280_REGISTER_DATA = 0xF7 + +class BMP280: + def __init__(self, i2c_bus, addr=0x77): + self._bmp_i2c = i2c_bus + self._i2c_addr = addr + self.chip_id = self._read(BMP280_REGISTER_ID, 2) + + self._T1 = unp(' self._new_read_ms: + self._last_read_ts = now + r = self._t_os + (self._p_os << 3) + (1 << 6) + self._write(BMP280_REGISTER_CONTROL, r) + utime.sleep_ms(100) # TODO calc sleep + d = self._read(BMP280_REGISTER_DATA, 6) # read all data at once (as by spec) + self._p_raw = (d[0] << 12) + (d[1] << 4) + (d[2] >> 4) + self._t_raw = (d[3] << 12) + (d[4] << 4) + (d[5] >> 4) + self._t_fine = 0 + self._t = 0 + self._p = 0 + + def load_test_calibration(self): + self._T1 = 27504 + self._T2 = 26435 + self._T3 = -1000 + self._P1 = 36477 + self._P2 = -10685 + self._P3 = 3024 + self._P4 = 2855 + self._P5 = 140 + self._P6 = -7 + self._P7 = 15500 + self._P8 = -14600 + self._P9 = 6000 + + def load_test_data(self): + self._t_raw = 519888 + self._p_raw = 415148 + + def print_calibration(self): + print("T1: {} {}".format(self._T1, type(self._T1))) + print("T2: {} {}".format(self._T2, type(self._T2))) + print("T3: {} {}".format(self._T3, type(self._T3))) + print("P1: {} {}".format(self._P1, type(self._P1))) + print("P2: {} {}".format(self._P2, type(self._P2))) + print("P3: {} {}".format(self._P3, type(self._P3))) + print("P4: {} {}".format(self._P4, type(self._P4))) + print("P5: {} {}".format(self._P5, type(self._P5))) + print("P6: {} {}".format(self._P6, type(self._P6))) + print("P7: {} {}".format(self._P7, type(self._P7))) + print("P8: {} {}".format(self._P8, type(self._P8))) + print("P9: {} {}".format(self._P9, type(self._P9))) + + def _calc_t_fine(self): + # From datasheet page 22 + self._gauge() + if self._t_fine == 0: + var1 = (((self._t_raw >> 3) - (self._T1 << 1)) * self._T2) >> 11 + var2 = (((((self._t_raw >> 4) - self._T1) * ((self._t_raw >> 4) - self._T1)) >> 12) * self._T3) >> 14 + self._t_fine = var1 + var2 + + # @property + def get_BMP_temperature(self): + self._calc_t_fine() + if self._t == 0: + self._t = ((self._t_fine * 5 + 128) >> 8) / 100. + return self._t + + # @property + def get_BMP_pressure(self): + # From datasheet page 22 + self._calc_t_fine() + if self._p == 0: + var1 = self._t_fine - 128000 + var2 = var1 * var1 * self._P6 + var2 = var2 + ((var1 * self._P5) << 17) + var2 = var2 + (self._P4 << 35) + var1 = ((var1 * var1 * self._P3) >> 8) + ((var1 * self._P2) << 12) + var1 = (((1 << 47) + var1) * self._P1) >> 33 + + if var1 == 0: + return 0 + + p = 1048576 - self._p_raw + p = int((((p << 31) - var2) * 3125) / var1) + var1 = (self._P9 * (p >> 13) * (p >> 13)) >> 25 + var2 = (self._P8 * p) >> 19 + + p = ((p + var1 + var2) >> 8) + (self._P7 << 4) + self._p = p / 256.0 + return self._p diff --git a/mixly/boards/default/micropython/build/lib/cbr817.py b/mixly/boards/default/micropython/build/lib/cbr817.py new file mode 100644 index 00000000..37d93cf3 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/cbr817.py @@ -0,0 +1,117 @@ +""" +CBR817 + +MicroPython library for the CBR817 (Microwave radar sensor) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from machine import Pin +from micropython import const + +CBR_ADDRESS = const(0x71) +CBR_OP_SET = const(0x02) +CBR_TX_RF = const(0x03) +CBR_POWER = const(0x04) +CBR_LIGHT = const(0x0B) +CBR_REG_CTR1 = const(0X13) +CBR_SENSOR_THR = const(0X18) +CBR_NOISE_THR = const(0X1A) +CBR_TRIGER = const(0x1C) +CBR_DELAY_TIM = const(0X1D) +CBR_LOCK_TIM = const(0X20) +CBR_SEL_REG = const(0x23) +CBR_REG_CTR2 = const(0X24) +CBR_FILTER = const(0x2A) +CBR_RESULT = const(0x81) + +class CBR817: + def __init__(self, i2c_bus, addr=CBR_ADDRESS, tx_power=3, threshold=5000, noise=256, delay=500, lock=500): + self._device = i2c_bus + self._address = addr + + self._configure() + self.tx_power(tx_power) + self.threshold(threshold) + self.noise(noise) + self.delay_ms(delay) + self.lock_ms(lock) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address, reg, val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes <= 1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _wake(self): + '''Wake up from low power consumption''' + try: + self._wreg(CBR_SEL_REG, 0xC0) + except : + pass + + def threshold(self, value=None): + self._wake() + if value is None: + return self._rreg(CBR_SENSOR_THR) | self._rreg(CBR_SENSOR_THR + 1) << 8 + else: + self._wreg(CBR_SENSOR_THR, value & 0xFF) + self._wreg(CBR_SENSOR_THR + 1, (value >> 8) & 0xFF) + + def noise(self, value=None): + self._wake() + if value is None: + return self._rreg(CBR_NOISE_THR) | self._rreg(CBR_NOISE_THR + 1) << 8 + else: + self._wreg(CBR_NOISE_THR, value & 0xFF) + self._wreg(CBR_NOISE_THR + 1, (value >> 8) & 0xFF) + + def delay_ms(self, value=None): + self._wake() + if value is None: + return round((self._rreg(CBR_DELAY_TIM) | self._rreg(CBR_DELAY_TIM + 1) << 8 | self._rreg(CBR_DELAY_TIM + 2) << 16) / 32) + else: + value = value * 32 + self._wreg(CBR_DELAY_TIM, value & 0xFF) + self._wreg(CBR_DELAY_TIM + 1, (value >> 8) & 0xFF) + self._wreg(CBR_DELAY_TIM + 2, (value >> 16) & 0xFF) + + def lock_ms(self, value=None): + self._wake() + if value is None: + return round((self._rreg(CBR_LOCK_TIM) | self._rreg(CBR_LOCK_TIM + 1) << 8 | self._rreg(CBR_LOCK_TIM + 2) << 16) // 32) + else: + value = value * 32 + self._wreg(CBR_LOCK_TIM, value & 0xFF) + self._wreg(CBR_LOCK_TIM + 1, (value >> 8) & 0xFF) + self._wreg(CBR_LOCK_TIM + 2, (value >> 16) & 0xFF) + + def tx_power(self, value=None): + self._wake() + if value is None: + return self._rreg(CBR_TX_RF) & 0x07 + else: + self._wreg(CBR_TX_RF, (value & 0x07) | 0x30) + + def _configure(self): + self._wake() + self._wreg(CBR_SEL_REG, 0xC0) #唤醒射频芯片 + _star = time.ticks_ms() + while self._rreg(CBR_SEL_REG) != 0xC0: + self._wreg(CBR_SEL_REG, 0xC0) + time.sleep_us(10) + if time.ticks_diff(time.ticks_ms(), _star) >= 200: + raise AttributeError("Cannot find a CBR817") + self._wreg(CBR_TRIGER, 0x55) #连续检测 + self._wreg(CBR_LIGHT, 0x12) #关闭光敏 + self._wreg(CBR_POWER, 0xA0) #功耗全供电 + self._wreg(CBR_FILTER, 0x0F) #打开滤波器 + self._wreg(CBR_OP_SET, 0x5C) #单运放,0.5uA电流 + self._wreg(CBR_REG_CTR1, 0X61) #感应门限和噪声门限改寄存器控制 + self._wreg(CBR_REG_CTR2, 0X60) #延时时间和闭锁时间改寄存器控制 + + def result(self): + self._wake() + return bool(self._rreg(CBR_RESULT) & 0x20) diff --git a/mixly/boards/default/micropython/build/lib/cc_g1.py b/mixly/boards/default/micropython/build/lib/cc_g1.py new file mode 100644 index 00000000..998854ea --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/cc_g1.py @@ -0,0 +1,85 @@ +""" +CC_G1 + +Micropython library for the CC_G1(Remote control handle) +======================================================= + +#Preliminary composition 20231222 + +@dahanzimin From the Mixly Team +""" +from micropython import const +from machine import Pin,SoftI2C + +_CC_G1_ADDRESS = const(0x27) +_CC_G1_ID = const(0x00) +_CC_G1_VBAT = const(0x01) +_CC_G1_ADC = const(0x03) +_CC_G1_KEY = const(0x07) + +class Handle: + def __init__(self, i2c_bus, addr=_CC_G1_ADDRESS): + self._i2c=i2c_bus + self._addr = addr + if self._rreg(_CC_G1_ID)!= 0x27: + raise AttributeError("Cannot find a CC_G1") + + def _wreg(self, reg, val): + '''Write memory address''' + try: + self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little')) + except: + return 0 + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + try: + self._i2c.writeto(self._addr, reg.to_bytes(1, 'little')) + return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes<=1 else self._i2c.readfrom(self._addr, nbytes)[0:nbytes] + except: + return 0 + + def read_bat(self, ratio=5/1023): + '''Read battery power''' + vbat = self._rreg(_CC_G1_VBAT)<<2 | self._rreg(_CC_G1_VBAT+1)>>6 + return round(vbat*ratio, 2) + + def read_joystick(self, ratio=100/1023): + '''Read joystick''' + y_axis = 1023 - (self._rreg(_CC_G1_ADC) << 2 | self._rreg(_CC_G1_ADC + 1) >> 6) + x_axis = self._rreg(_CC_G1_ADC + 2 ) << 2 | self._rreg(_CC_G1_ADC + 3) >> 6 + return round(x_axis*ratio), round(y_axis*ratio) + + def read_key(self, index): + '''Read key1~6''' + if not 0 <= index <= 5: + raise ValueError("The key number must be a number in the range: 0~5") + if index<=4: + return bool(self._rreg(_CC_G1_KEY) >> index & 0x01) + else: + return bool(self._rreg(_CC_G1_KEY) >> 7 & 0x01) + + def shutdown(self, flag=True): + """This function is only available on battery power""" + if flag: + self._wreg(_CC_G1_KEY, (self._rreg(_CC_G1_KEY)) & 0XBF) + else: + self._wreg(_CC_G1_KEY, (self._rreg(_CC_G1_KEY)) | 0X40) + +'''Select instantiation objects''' +try: + #MixGo CC/ME + ext_i2c = SoftI2C(scl=Pin(0), sda=Pin(1), freq=100000) + handle = Handle(ext_i2c) +except: + try: + #MixGo CE + ext_i2c = SoftI2C(scl=Pin(17), sda=Pin(18), freq=100000) + handle = Handle(ext_i2c) + except: + try: + #MixGo Mini + ext_i2c = SoftI2C(scl=Pin(8), sda=Pin(7), freq=100000) + handle = Handle(ext_i2c) + except: + print("MixGo board cannot find a CC_G1") diff --git a/mixly/boards/default/micropython/build/lib/ch914x_at.py b/mixly/boards/default/micropython/build/lib/ch914x_at.py new file mode 100644 index 00000000..218d6482 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ch914x_at.py @@ -0,0 +1,147 @@ +""" +Bluetooth AT + +Micropython library for the Bluetooth AT(WCH) +======================================================= + +#Preliminary composition 20230106 + +dahanzimin From the Mixly Team +""" +from machine import Pin +from time import sleep_ms + +class AT: + def __init__(self, pin,times=5): + self.at_pin = Pin(pin, Pin.OUT) + self.at_pin.value(1) + self._times = times + self._flag = [0,0,0,0,0,0,0,0] #mac0,1 name2,3 power4,5 power6,7 + self._power = [0,1,2,3,-3,-8,-14,-20] + sleep_ms(100) + + def _str_reverse(self,data): + data=data.split(':') + data.reverse() + data=":".join(data) + return data + + def ble_mac(self, mac=None): + sleep_ms(200) + if mac is None: + if not (self._flag[0] >= self._times and self._times != 0): + self._flag[0]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+MAC?\r\n') + input() + self.at_pin.value(1) + print('BLE_MAC:',self._str_reverse(data)) + sleep_ms(100) + return self._str_reverse(data) + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[1] >= self._times and self._times != 0): + self._flag[1]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+MAC={}\r\n'.format(self._str_reverse(mac))) + print('\r\n') + self.at_pin.value(1) + print('BLE_MAC:',mac,data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') + + def ble_name(self, name=None): + sleep_ms(200) + if name is None: + if not (self._flag[2] >= self._times and self._times != 0): + self._flag[2]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+NAME?\r\n') + input() + input() + self.at_pin.value(1) + print('BLE_NAME:',data) + sleep_ms(100) + return data + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[3] >= self._times and self._times != 0): + self._flag[3]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+NAME='+name+'\r\n') + print('\r\n') + self.at_pin.value(1) + print('BLE_NAME:',name,data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') + + def ble_power(self, power=None): + sleep_ms(200) + if power is None: + if not (self._flag[4] >= self._times and self._times != 0): + self._flag[4]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+TPL?\r\n') + input() + print(' \r\n') + self.at_pin.value(1) + data=self._power[int(data[4:])] + print('BLE_Power: {}DB'.format(data)) + sleep_ms(100) + return data + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[5] >= self._times and self._times != 0): + self._flag[5]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+TPL={}\r\n'.format(self._power.index(power))) + print('\r\n') + self.at_pin.value(1) + print('BLE_Power:',str(power)+'DB',data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') + + def ble_pname(self, name=None): + sleep_ms(200) + if name is None: + if not (self._flag[6] >= self._times and self._times != 0): + self._flag[6]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+PNAME?\r\n') + input() + input() + self.at_pin.value(1) + print('BLE_PNAME:',data) + sleep_ms(100) + return data + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[7] >= self._times and self._times != 0): + self._flag[7]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+PNAME='+name+'\r\n') + print('\r\n') + self.at_pin.value(1) + print('BLE_PNAME:',name,data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') diff --git a/mixly/boards/default/micropython/build/lib/ci130x.py b/mixly/boards/default/micropython/build/lib/ci130x.py new file mode 100644 index 00000000..11152caa --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ci130x.py @@ -0,0 +1,129 @@ +""" +CI130X + +MicroPython library for the CI130X (ASR-I2C) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from struct import pack +from micropython import const + +_CI_ADDRESS = const(0x64) +_CI_ID_GET = const(0x02) +_CI_ID_SET = const(0x03) +_CI_ID_NUM = const(0x06) +_CI_ID_CLE = const(0x07) +_CI_ID_PACTRL = const(0x09) +_CI_ID_ASREN = const(0x0A) +_CI_ID_END = const(0x5A) +_TIME_SNUM = const(0x75) + +class CI130X: + def __init__(self, i2c_bus, addr=_CI_ADDRESS): + self._device = i2c_bus + self._address = addr + self._cmd_id = None + self._enable = True + try: + self._rreg(_CI_ID_GET, 3) + except: + try: #C130X 启动慢,加延时判断 + time.sleep_ms(850) + self._rreg(_CI_ID_GET, 3) + except: + raise AttributeError("Cannot find a CI130X") + + def _wreg(self, reg): + '''Write memory address''' + self._device.writeto(self._address, reg) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes) + + def status(self): + """返回 (是否唤醒, 是否播放)""" + _buf = self._rreg(_CI_ID_GET, 3) + return (bool(_buf[1] & 0x01), bool(_buf[1] & 0x10)) if _buf[2] == _CI_ID_END else (None, None) + + def cmd_id(self, repeat=False): + """返回 识别命令词对应ID""" + _buf = self._rreg(_CI_ID_GET, 3) + if not repeat: + self._wreg(bytes([_CI_ID_CLE, 0, 0, _CI_ID_END])) + time.sleep_ms(50) + self._cmd_id = _buf[0] if _buf[2] == _CI_ID_END else None + return self._cmd_id + + def result(self, ext_id=None): + """获取比较结果 或者输出结果""" + return self._cmd_id if ext_id is None else bool(self._cmd_id == ext_id) + + def sys_cmd(self, value, blocking=True): + """系统命令,1,2唤醒 202~205音量调整 206,207回复播报开关 208退出唤醒""" + self.play_id(value, blocking) + + def play_id(self, value, blocking=True): + """播放命令词对应ID语音""" + self._wreg(bytes([_CI_ID_SET, value, 0, _CI_ID_END])) + while blocking: + time.sleep_ms(15) + if not self.status()[1]: + break + + def play_num(self, value, blocking=True): + """播放浮点数据的合成语音""" + self._wreg(bytes([_CI_ID_NUM]) + pack('d', float(value)) + bytes([0, _CI_ID_END])) + while blocking: + time.sleep_ms(10) + if not self.status()[1]: + break + + def play(self, star=None, num=None, end=None, delay=10): + """组合播报名词+数值+单位""" + if star is not None: + self.play_id(star) + time.sleep_ms(delay) + if num is not None: + self.play_num(num) + time.sleep_ms(delay) + if end is not None: + self.play_id(end) + time.sleep_ms(delay) + + def play_time(self, times=None, detail=True, delay=10): + """播报时间""" + data = time.localtime() if times is None else times + if detail: + for i in range(0, 3): #年 月 日 + self.play_num(data[i]) + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + i) + time.sleep_ms(delay) + + for i in range(3, 5): #时 分 + self.play_num(data[i]) + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + i) + time.sleep_ms(delay) + + if detail: + self.play_num(data[5]) #秒 + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + 5) + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + 6) #星期 + time.sleep_ms(delay) + self.play_num(data[6] + 1) + + def pa_ctrl(self, value=True, delay=10): + self._wreg(bytes([_CI_ID_PACTRL, int(value), 0, _CI_ID_END])) + if value: time.sleep_ms(delay) + + def asr_en(self, value=None): + if value is None: + return self._enable + else: + self._enable = bool(value) + self._wreg(bytes([_CI_ID_ASREN, self._enable, 0, _CI_ID_END])) diff --git a/mixly/boards/default/micropython/build/lib/debugnet.py b/mixly/boards/default/micropython/build/lib/debugnet.py new file mode 100644 index 00000000..b2955ec9 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/debugnet.py @@ -0,0 +1,166 @@ +""" +Debugnet(HTTP,MQTT) + +MicroPython library for network request debugging +======================================================= + +#Preliminary composition 20230225 + +@dahanzimin From the Mixly Team +""" +import time +from umqtt import MQTTClient +from ubinascii import hexlify +from machine import unique_id +from urequests import Response +from usocket import socket,getaddrinfo,SOCK_STREAM +from mixiot import WILL_TOPIC,ADDITIONAL_TOPIC + +class socket_d(socket): + def __init__(self,*args,debug=False,**kw): + super().__init__(*args,**kw) + self._debug=debug + self.client_len=0 + self.server_len=0 + + def write(self,*args): + super().write(*args) + self.client_len=min(self.client_len+len(args[0]),65535) + if self._debug: + print('client:',args[0]) + + def readline(self,*args): + buf=super().readline(*args) + self.server_len=min(self.server_len+len(buf),65535) if buf else self.server_len + if self._debug: + print('server:',buf) + return buf + + def read(self,*args): + buf=super().read(*args) + self.server_len=min(self.server_len+len(buf),65535) if buf else self.server_len + if self._debug: + print('server:',buf) + return buf + +#HTTP +def request(method, url, data=None, json=None, headers={}, stream=None, parse_headers=True, debug=False): + redir_cnt = 1 + while True: + try: + proto, dummy, host, path = url.split("/", 3) + except ValueError: + proto, dummy, host = url.split("/", 2) + path = "" + if proto == "http:": + port = 80 + elif proto == "https:": + import ussl + port = 443 + else: + raise ValueError("Unsupported protocol: " + proto) + if ":" in host: + host, port = host.split(":", 1) + port = int(port) + ai = getaddrinfo(host, port, 0, SOCK_STREAM) + ai = ai[0] + resp_d = None + if parse_headers is not False: + resp_d = {} + s = socket_d(ai[0], ai[1], ai[2], debug=debug) + try: + s.connect(ai[-1]) + if proto == "https:": + s = ussl.wrap_socket(s, server_hostname=host) + s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) + if not "Host" in headers: + s.write(b"Host: %s\r\n" % host) + for k in headers: + s.write(k) + s.write(b": ") + s.write(headers[k]) + s.write(b"\r\n") + if json is not None: + assert data is None + import ujson + data = ujson.dumps(json) + s.write(b"Content-Type: application/json\r\n") + if data: + s.write(b"Content-Length: %d\r\n" % len(data)) + s.write(b"Connection: close\r\n\r\n") + if data: + s.write(data) + l = s.readline() + l = l.split(None, 2) + status = int(l[1]) + reason = "" + if len(l) > 2: + reason = l[2].rstrip() + while True: + l = s.readline() + if not l or l == b"\r\n": + break + if l.startswith(b"Transfer-Encoding:"): + if b"chunked" in l: + raise ValueError("Unsupported " + l) + elif l.startswith(b"Location:") and 300 <= status <= 399: + if not redir_cnt: + raise ValueError("Too many redirects") + redir_cnt -= 1 + url = l[9:].decode().strip() + status = 300 + break + if parse_headers is False: + pass + elif parse_headers is True: + l = l.decode() + k, v = l.split(":", 1) + resp_d[k] = v.strip() + else: + parse_headers(l, resp_d) + except OSError: + s.close() + raise + if status != 300: + break + resp = Response(s) + resp.status_code = status + resp.reason = reason + resp.client_len=s.client_len + resp.server_len=s.server_len + if resp_d is not None: + resp.headers = resp_d + return resp + +class MQTT_Client(MQTTClient): + def __init__(self,*args,debug=False,**kw): + super().__init__(*args,**kw) + self.sock = socket_d(debug=debug) + + @property + def client_len(self): #The length of client data obtained + _len=self.sock.client_len + self.sock.client_len=0 + return _len + + @property + def server_len(self): #The length of server data obtained + _len=self.sock.server_len + self.sock.server_len=0 + return _len + + def time_msg(self,utc=28800): #Get server time information + msg=self.wait_msg() + if isinstance(msg, dict): + if msg['topic'] =='$SYS/hello': + val=time.gmtime(int(msg['msg'])//1000-946684800+utc)[0:7] + return str(val).replace(' ','')[1:-1] + +#MQTT +def init_MQTT_client(address, username, password, MQTT_USR_PRJ, debug=False): + client = MQTT_Client(hexlify(unique_id()), address, 1883, username, password, debug=debug) + client.set_last_will(topic=MQTT_USR_PRJ+WILL_TOPIC, msg=client.client_id, qos=2) + if client.connect()==0: + client.publish(MQTT_USR_PRJ+ADDITIONAL_TOPIC, client.client_id, qos=0) + time.sleep_ms(200) + return client diff --git a/mixly/boards/default/micropython/build/lib/dhtx.py b/mixly/boards/default/micropython/build/lib/dhtx.py new file mode 100644 index 00000000..0755ad6f --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/dhtx.py @@ -0,0 +1,60 @@ +# DHT11/DHT22 driver for MicroPython +# MIT license; Copyright (c) 2016 Damien P. George + +from time import sleep +try: + from esp import dht_readinto +except: + from machine import dht_readinto +from machine import Pin + +class DHTBase: + __species = {} + __first_init = True + def __new__(cls, pin, *args, **kwargs): + if pin not in cls.__species.keys(): + cls.__first_init = True + cls.__species[pin] = object.__new__(cls) + return cls.__species[pin] + + def __init__(self, pin): + if self.__first_init: + self.__first_init = False + self.pin = Pin(pin) + self.buf = bytearray(5) + self.err = 0 + + def measure(self): + buf = bytearray(5) + try: + dht_readinto(self.pin, buf) + if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF == buf[4]: + self.buf = buf + self.err = 0 + except: + if self.err > 10: + raise AttributeError("DHTx operation error") + self.err += 1 + sleep(0.5) + return + +class DHT11(DHTBase): + def humidity(self): + self.measure() + return self.buf[0] + + def temperature(self): + self.measure() + return self.buf[2] + +class DHT22(DHTBase): + def humidity(self): + self.measure() + return (self.buf[0] << 8 | self.buf[1]) * 0.1 + + def temperature(self): + self.measure() + t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1 + if self.buf[2] & 0x80: + t = -t + return t diff --git a/mixly/boards/default/micropython/build/lib/ds18b20.py b/mixly/boards/default/micropython/build/lib/ds18b20.py new file mode 100644 index 00000000..fae95bc5 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ds18b20.py @@ -0,0 +1,67 @@ +# DS18x20 temperature sensor driver for MicroPython. +# MIT license; Copyright (c) 2016 Damien P. George + +import onewire +from machine import Pin +from micropython import const + +_CONVERT = const(0x44) +_RD_SCRATCH = const(0xBE) +_WR_SCRATCH = const(0x4E) + +class DS18X20: + __species = {} + __first_init = True + def __new__(cls, pin, *args, **kwargs): + if pin not in cls.__species.keys(): + cls.__first_init = True + cls.__species[pin] = object.__new__(cls) + return cls.__species[pin] + + def __init__(self, pin): + if self.__first_init: + self.__first_init = False + self._ow = onewire.OneWire(Pin(pin, pull=Pin.PULL_UP)) + self._buf = bytearray(9) + self._roms = self.scan() + if len(self._roms) == 0: + raise AttributeError("Cannot find a DS18X20") + + def scan(self): + return [rom for rom in self._ow.scan() if rom[0] in (0x10, 0x22, 0x28)] + + def convert_temp(self): + self._ow.reset(True) + self._ow.writebyte(self._ow.SKIP_ROM) + self._ow.writebyte(_CONVERT) + + def read_scratch(self, rom): + self._ow.reset(True) + self._ow.select_rom(rom) + self._ow.writebyte(_RD_SCRATCH) + self._ow.readinto(self._buf) + if self._ow.crc8(self._buf): + raise Exception("CRC error") + return self._buf + + def read_temp(self, rom): + buf = self.read_scratch(rom) + if rom[0] == 0x10: + if buf[1]: + t = buf[0] >> 1 | 0x80 + t = -((~t + 1) & 0xFF) + else: + t = buf[0] >> 1 + return t - 0.25 + (buf[7] - buf[6]) / buf[7] + else: + t = buf[1] << 8 | buf[0] + if t & 0x8000: # sign bit set + t = -((t ^ 0xFFFF) + 1) + return t / 16 + + def temperature(self): + temp = [] + self.convert_temp() + for rom in self._roms: + temp.append(round(self.read_temp(rom), 2)) + return temp [0] if len(temp) == 1 else tuple(temp) diff --git a/mixly/boards/default/micropython/build/lib/expression_picture.py b/mixly/boards/default/micropython/build/lib/expression_picture.py new file mode 100644 index 00000000..a0cab8ba --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/expression_picture.py @@ -0,0 +1,21 @@ +#Take the picture bytes in expression_picture.py +#--dahanzimin From the Mixly Team + +Angry=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x01\x87\xfc\x00\x00\x7f\x80\x00\x01\xd9\xfe\x00\x00\xff\x00\x00\x07\xfc\xff\x00\x01\xfe\x00\x00\x07\xfe\x7f\x80\x01\xfc\x00\x00\x03\x1c?\x80\x03\xf8\x00\x00\x0f\x18\x1f\xc0\x03\xf0\x00\x00\x0e\xdc\x0f\xc0\x07\xf0\x00\x00\x07\xfc\x0f\xe0\x07\xe0\x00\x00\x07\xf8\x07\xe0\x0f\xc0\x00\x00\x02`\x03\xf0\x0f\xc0\x00\x00\x00 \x03\xf0\x1f\xc0\x00\x00\x00\x00\x03\xf8\x1f\x83\x00\x00\x00\x00\xc1\xf8\x1f\x83\xc0\x00\x00\x03\xc1\xf8\x1f\x03\xf0\x00\x00\x1f\xc1\xf8?\x07\xfe\x00\x00?\xe0\xfc?\x03\xff\x80\x01\xff\xc0\xfc?\x03\xff\xe0\x07\xff\xc0\xfc?\x03\xff\xe0\x03\xff\x80\xfc?\x01\xff\xc0\x03\xff\x80|?\x00\xff\x80\x01\xff\x00\xfc>\x00>\x00\x00|\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xc0\x00\x00\x00\x00\x07\xf0\x07\xe0\x00\x03\x80\x00\x07\xe0\x07\xf0\x00\x07\xc0\x00\x0f\xe0\x03\xf0\x00\x0f\xf0\x00\x0f\xc0\x03\xf8\x00\x1e\xf8\x00\x1f\xc0\x01\xfc\x00\x1c~\x00?\x80\x01\xfe\x00\x00\x1c\x00\x7f\x80\x00\xff\x00\x00\x04\x00\xff\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x05\xff\xe0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Bored=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x0f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\x80\x00\x00\x00\x00\x03\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x83[\x00\x00\xdfA\xf8\x1f\x87\xff\x80\x01\xff\xe0\xf8?\x07\xff\x00\x01\xff\xe0\xfc?\x01}\x00\x00\x8e\x00\xfc?\x000\x00\x00\x0e\x00\xfc?\x00p\x00\x00\x1c\x00\xfc>\x05~\x80\x00_\xc0|?\x07\xff\x80\x01\xff\xe0\xfc?\x07\xff\x80\x01\xff\xe0\xfc>\x02D\x00\x00\xa4\x80|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x07\xf0\x00\x03\xf0\x0f\xe0\x00\x1f\xfc\x00\x07\xf0\x07\xe0\x00?\xfe\x00\x07\xe0\x07\xf0\x00|\x1f\x00\x07\xe0\x03\xf8\x00p\x07\x00\x1f\xc0\x03\xf8\x00\xe0\x07\x80\x1f\xc0\x01\xfc\x00s\xe3\x80?\x80\x00\xfe\x00c\xf3\x00\x7f\x00\x00\xff\x00\x03\xe0\x00\xff\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xfa\xbf\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfe\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x00_\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Confused=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x06\x00\x00\x00\x1f\xc0\x03\xf0\x0f\x00\x01\xfc\x1f\xc0\x07\xf0\x1f\x00\x01\xff\x0f\xe0\x07\xe0?\x00\x01\xff\x87\xe0\x0f\xc0~\x00\x00\xff\xc7\xf0\x0f\xdf\xfc\x00\x00\x07\xe3\xf0\x1f\xdf\xf8\x00\x00\x01\xf3\xf8\x1f\x9f\xe0\x00\x00\x00\xf1\xf8\x1f\x8f(\x00\x00\x18\xe1\xf8\x1f\x00~\x00\x00~!\xf8?\x00\xff\x00\x00\xfe\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00~\x00\x00\xfe\x00\xfc>\x00>\x00\x00|\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xf8?\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xe0\x00\x00\x00\x00\x03\xf0\x07\xe0\x00\x00\x00\x00\x07\xe0\x07\xf0\x00\x1f\x80\x00\x0f\xe0\x03\xf0\x00?\xc0\x00\x0f\xc0\x03\xf8\x00?\xc7\x00\x1f\xc0\x01\xfc\x009\xe7\x00?\x80\x00\xfe\x001\xe7\x00\x7f\x80\x00\xff\x000\xfe\x00\xff\x00\x00\x7f\xc0\x00~\x03\xfe\x00\x00?\xe0\x00<\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xfe\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x01\xff\xff\x80\x00\x00\x00\x00\x00?\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Happy=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xff\x7f\xff\xc0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfe\x00\x00\x00\x00\x7f\x00\x03\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf8\x00\x00\x00\x00\x0f\xc0\x07\xe0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\xc0\x00\x00\x00\x00\x03\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x14\x00\x008\x01\xf8\x1f\x00~\x00\x00~\x00\xf8?\x00\xff\x00\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00\xff\x00\x00\xff\x00\xfc?\x00\x7f\x00\x00\xfe\x00|>\x00<\x00\x00|\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xf8?\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xe0\x02\xfa\xd5\x80\x07\xf0\x07\xe0\x03\xff\xff\xc0\x07\xe0\x07\xf0\x07\xff\xff\xe0\x0f\xe0\x03\xf8\x03\xff\xff\xc0\x0f\xc0\x03\xf8\x03\xff\xff\xc0\x1f\xc0\x01\xfc\x01\xff\xff\x80?\x80\x01\xfe\x01\xff\xff\x80\x7f\x80\x00\xff\x00\xff\xff\x00\xff\x00\x00\x7f\x80\x7f\xfe\x03\xfe\x00\x00?\xe0?\xfc\x07\xfc\x00\x00\x1f\xf0\x07\xf0\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xfe\xbf\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Heart=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfe\x00\x00\x7f\xc0\x00\x00\x1f\xff\xc0\x03\xff\xf8\x00\x00\x7f\xff\xf0\x0f\xff\xfe\x00\x00\xff\xff\xf8\x1f\xff\xff\x00\x01\xff\xff\xfe\x7f\xff\xff\x80\x03\xff\xff\xff\x7f\xff\xff\xc0\x07\xff\xff\xff\xff\xff\xff\xe0\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xfc\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xc0\x01\xff\xff\xff\xff\xff\xff\x80\x00\xff\xff\xff\xff\xff\xff\x80\x00\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xff\xff\xff\xfe\x00\x00?\xff\xff\xff\xff\xfc\x00\x00\x1f\xff\xff\xff\xff\xf8\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x01\xff\xff\xff\xff\xc0\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xfe\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x1f\xff\xff\xf8\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xff\x80\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x00?\xfe\x00\x00\x00\x00\x00\x00\x1f\xf8\x00\x00\x00\x00\x00\x00\x0f\xf0\x00\x00\x00\x00\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Paper=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x00\x00\x00\x00\x01\xff\x00`\x00\x00\x00\x00\x01\xff\x83\xfc\x00\x00\x00\x00\x07\xff\xc7\xff\x00\x00\x00\x00\x07\xe7\xcf\xff\x80\x00\x00\x00\x0f\x83\xff\xff\x80\x00\x00\x00\x0f\x03\xff\x07\x80\x00\x00\x00\x0f\x03\xfe\x07\xc0\x00\x00\x00\x1f\x01\xfc\x03\xc0\x00\x00\x00\x1e\x01\xf8\x03\xc0\x00\x00\x00\x1e\x01\xf8\x07\xcc\x00\x00\x00\x1e\x03\xf0\x07\xff\x00\x00\x00\x1e\x03\xe0\x0f\xff\x80\x00\xbc\x1e\x03\xe0\x0f\xff\xc0\x01\xff\x1e\x03\xc0\x1f\xff\xc0\x03\xff\xfe\x03\xc0?\xc3\xe0\x07\xff\xfe\x01\xc0?\x81\xe0\x07\xc7\xfe\x00\x00~\x01\xe0\x07\x81\xfe\x00\x00\xfc\x01\xe0\x0f\x80\xfe\x00\x01\xf8\x03\xe0\x0f\x80~\x00\x01\xf0\x07\xc0\x07\x80>\x00\x00\xe0\x0f\xc0\x07\x80\x1e\x00\x00@\x1f\x80\x07\xc0\x0e\x00\x00\x00?\x00\x03\xe0\x06\x00\x00\x00~\x00\x03\xe0\x06\x00\x00\x00\xfc\x00\x01\xf0\x02\x00\x00\x03\xff\x00\x00\xf8\x00\x00\x00\x07\xff\xc0\x00\xfc\x00\x00\x00\x07\xff\xe0\x00|\x00\x00\x00\x07\xff\xe0\x00>\x00\x00\x00\x03\x81\xf0\x00\x1e\x00\x00\x00\x00\x00\xf0\x00\x1e\x00\x00\x00\x00\x00\xf0\x00\x1e\x00\x00\x00\x00\x01\xf0\x00\x1e\x00\x00\x00\x00\x03\xf0\x00\x1e\x00\x00\x00\x00\x07\xe0\x00>\x00\x00\x00\x00\x7f\xc0\x00<\x00\x00\x00\xff\xff\x80\x00|\x00\x00\x01\xff\xff\x00\x00|\x00\x00\x03\xff\xfc\x00\x00<\x00\x00\x03\xff\xe0\x00\x00<\x00\x00\x07\xe0\x00\x00\x00>\x00\x00\x0f\x80\x00\x00\x00>\x00\x00\x1f\x80\x00\x00\x00\x1f\x00\x00?\x00\x00\x00\x00\x0f\x80\x00~\x00\x00\x00\x00\x0f\xc0\x00\xfc\x00\x00\x00\x00\x07\xf0\x03\xf8\x00\x00\x00\x00\x03\xf8\x07\xf0\x00\x00\x00\x00\x01\xff?\xc0\x00\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Rock=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\xc1\xff\xc0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x1f\xff\xff\xf0\x00\x00\x00\x00?\xff\xc3\xf8\x00\x00\x00\x00?\xff\x00\xff\xf0\x00\x00\x00|\x0f\x00\x7f\xfc\x00\x00\x00x\x0e\x00\xff\xfe\x00\x00\x07\xf8\x1e\x03\xff\xff\x00\x00\x1f\xf8\x1c\x0f\xf0\x1f\x80\x00?\xf0\x1c\x1f\x80\x0f\xc0\x00\x7f\xf0\x1c\x1e\x00\x07\xe0\x00\xfe\xf0\x1e<\x00\x03\xe0\x00\xf8p\x1e8\x00\x01\xe0\x00\xf0p\x0e8\x00\x01\xf0\x01\xf0x\x0e8\x00\x00\xf0\x01\xe0x\x0f8\x00\x00\xf0\x01\xe0<\x078\x00\x00\xf0\x01\xe0<\x07\xfc\x0f\x00\xf0\x03\xe0\x1e\x03\xbf\xff\x00\xf0\x0f\xf0\x1f\x03\xff\xff\x00\xf8\x1f\xf0\x0f\x81\xef\xfc\x00\xf8\x1f\xf0\x07\xc0\xff\xe0\x00x>x\x03\xe0\xff\x80\x00\xf8><\x01\xf1\xfc\x00\x00\xf8<>\x00\xff\xf0\x00\x00\xf8<\x1f\x00\x7f\xc0\x00\x00\xf0<\x0f\x80?\x00\x00\x00\xf0>\x07\xc0~\x00\x00\x00\xf0\x1e\x03\xe1\xf8\x00\x00\x00\xf0\x1f\x01\xf3\xf0\x00\x00\x01\xf0\x1f\x00\xff\xc0\x00\x00\x01\xe0\x0f\x80\x7f\x80\x00\x00\x01\xe0\x0f\x80\x1f\x00\x00\x00\x03\xe0\x07\xc0\x1e\x00\x00\x00\x03\xe0\x03\xe0<\x00\x00\x00\x07\xc0\x03\xf8x\x00\x00\x00\x0f\xc0\x01\xfcx\x00\x00\x00\x1f\x80\x00\xff\xf0\x00\x00\x00\x7f\x00\x00?\xf0\x00\x00\x01\xfe\x00\x00\x1f\xf0\x00\x00\x07\xfc\x00\x00\x07\xf0\x00\x00\x1f\xf0\x00\x00\x00\xf8\x00\x00?\xc0\x00\x00\x00|\x00\x00\xff\x80\x00\x00\x00~\x00\x03\xfe\x00\x00\x00\x00?\x00\x0f\xf8\x00\x00\x00\x00\x1f\x80?\xe0\x00\x00\x00\x00\x1f\xe0\xff\x80\x00\x00\x00\x00\x07\xff\xfe\x00\x00\x00\x00\x00\x03\xff\xf8\x00\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x00\x00\x7f\xc0\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Sad=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfe\xff\xff\xc0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x1f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x0f\xe0\x00\x00\x00\x00\x07\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\xc0\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8?\x00\x00\x00\x00\x00\x01\xfc\x1f\x07\xff\xe0\x0f\xff\xc0\xf8?\x07\xff\xe0\x0f\xff\xe0\xfc?\x07\xff\xf0\x0f\xff\xc0\xfc?\x07\xff\xe0\x0f\xff\xc0\xfc?\x00\x7f\x00\x00\xfe\x00\xfc?\x00?\x00\x00\xfc\x00\xfc>\x00\x7f\x00\x00\xfe\x00|?\x00?\x00\x00~\x00\xfc?\x00~\x00\x00\xfe\x00\xfc?\x00?\x00\x00\xfe\x00\xfc?\x00\x7f\x00\x00\xfc\x00\xfc\x1f\x00\x7f\x00\x00\xfe\x00\xf8\x1f\x00?\x00\x00\xfe\x01\xfc\x1f\x80\x7f\x00\x00\xfe\x01\xf8\x1f\x80\x7f\x00\x00\xfe\x01\xf8\x1f\xc0?\x00\x00|\x01\xf8\x0f\xc0\x7f\x00\x00\xfe\x03\xf0\x0f\xe0\x7f\x0f\xe0\xfe\x03\xf0\x07\xe0?\x1f\xf8\xfe\x07\xe0\x07\xf0\x7f\x7f\xfe\xfc\x0f\xe0\x03\xf0\x7f|?~\x0f\xc0\x03\xf8?\xf0\x0f\xfe\x1f\xc0\x01\xfc\x7f\xe0\x07\xfe?\x80\x00\xfe\x7f\xc0\x03\xfe\x7f\x00\x00\xff?@\x02\xfe\xff\x00\x00\x7f\xff\x00\x00\xff\xfe\x00\x00?\xff\x00\x00\xff\xfc\x00\x00\x1f\xff\x00\x00\xff\xf8\x00\x00\x0f\xff\x00\x00\xff\xf0\x00\x00\x07\xff\xc0\x00\xff\xe0\x00\x00\x01\xff\xff\x7f\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Scissors=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x00\x00\x00\x00\x00?\xf0\x00\x00\x00\x00\x00\x00\xff\xfc\x00\x00\x00\x00\x00\x01\xff\xff\x00\x00\x00\x00\x00\x01\xf8\xff\x80\x00\x00\x00\x00\x03\xe0\x1f\xc0\x00\x00\x00\x00\x07\xc0\x07\xf0\x00\x00\x00\x00\x07\xc0\x03\xf8\x00\x00\x00\x00\x07\x80\x01\xfc\x00\x00\x00\x00\x07\x80\x00~\x00\x00\x00\x00\x07\x80\x00?\x00\x00\x00\x00\x07\x80\x00\x1f\xfc\x00\x00\x00\x07\xc0\x00\x0f\xff\x80\x00\x00\x03\xe0\x00\x07\xff\xe0\x00\x00\x03\xf0\x00\x03\xff\xf8\x00\x00\x01\xf8\x00\x00\xe7\xfc\x00\x00\x00\xfc\x00\x01\xe0\xfe\x00\x00\x00\x7f\x00\x01\xe0?\x00\x00\x03\xff\x80\x01\xc0\x1f\x80\x00\x7f\xff\xe0\x03\xc0\x1f\x80\x01\xff\xff\xf8\x03\x80\x1f\xc0\x03\xff\xff\xff\x03\x80\x1f\xe0\x07\xff\xff\xff\x07\x80\x1f\xe0\x0f\xc0\x01\xff\x07\x00\x1f\xe0\x0f\x80\x00\x1e\x07\x00=\xf0\x1f\x00\x00\x00\x07\x00<\xf0\x1e\x00\x00\x00\x07\x008\xf0\x1e\x00\x00\x00\x0f\x00x\xf0\x1e\x00\x00\x00\x7f\x00\xf0\xf0\x1f\x00\x00\x01\xff\x00\xf0\xf8\x0f\x00\x00\x07\xff\x01\xe0\xf8\x0f\x80\x00\x0f\xef\x03\xc0x\x0f\xe0\x00?\x07\x87\xc0\xf8\x07\xff\x7f\xfe\x03\xff\x80\xf8\x03\xff\xff\xfc\x03\xff\x00\xf8\x01\xff\xff\xf8\x01\xfe\x00\xf0\x00\x7f\xff\xf8\x07\xff\x00\xf0\x00\x01\xd0|\x7f\xff\xc0\xf0\x00\x00\x00\x7f\xff\xff\xe0\xf0\x00\x00\x00?\xfc\x01\xf1\xf0\x00\x00\x00\x1f\xe0\x00\xf1\xe0\x00\x00\x00\x0f\x00\x00s\xe0\x00\x00\x00\x0f\x00\x00s\xe0\x00\x00\x00\x0f\x00\x00\xff\xc0\x00\x00\x00\x0f\x00\x00\xff\x80\x00\x00\x00\x0f\x80\x03\xff\x00\x00\x00\x00\x07\xf0\xff\xfe\x00\x00\x00\x00\x07\xff\xff\xfc\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xfe\x00\x00\x00\x00\x00\x007@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Silly=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xf4\x1f\xff\xc0\x00\x00\x07\xff\x00\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x1f\xf0\x00\x00\x0f\xf8\x00\x00?\xc0\x00\x00\x03\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfc\x00\x00\x00\x00?\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x07\xf0\x01\x00\x00\x00\x0f\xc0\x07\xe0\x03\x80\x01\xe0\x07\xe0\x07\xe0\x07\x80\x01\xe0\x07\xe0\x0f\xc0\x0f\x80\x01\xf0\x03\xf0\x0f\xc0?\x00\x00\xfc\x03\xf0\x1f\x87\xfe\x00\x00\x7f\xe1\xf8\x1f\x87\xfc\x00\x00?\xe1\xf8\x1f\x07\xf8\x00\x00\x0f\xf0\xf8\x1f\x07\xcc\x00\x00s\xe1\xf8?\x00\x1f\x00\x00\xf8\x00\xfc?\x00?\x80\x01\xfc\x00\xfc?\x00\x7f\xc0\x03\xfc\x00|>\x00\x7f\xc0\x01\xfe\x00\xfc>\x00?\x80\x03\xfe\x00|>\x00?\x80\x01\xfc\x00|?\x00?\x80\x00\xf8\x00|>\x00\x0e\x00\x00p\x00\xfc>\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x03\xc0\x00\x00\xf8?\x00\x00\x07\xe0\x00\x00\xfc\x1f\x00\x00\x0f\xe0\x00\x00\xf8\x1f\x80\x00\x07\xe0\x00\x01\xf8\x1f\x80\x00\x07\xf0\x00\x01\xf8\x0f\xc0\x00\x0f\xe0\x00\x03\xf0\x0f\xc0\x00\x0f\xe0\x00\x03\xf0\x07\xe0\x00\x07\xe0\x00\x07\xe0\x07\xe0\x00\x07\xf0\x00\x07\xe0\x07\xf0\x00\x0f\xe0\x00\x0f\xc0\x03\xf8\x00\x07\xe0\x00\x1f\xc0\x01\xfc\x00\x0f\xf0\x00?\x80\x00\xfc\x00\x07\xe0\x00?\x00\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\x80\x07\xc0\x01\xfe\x00\x00?\xc0\x00\x80\x03\xfc\x00\x00\x1f\xf0\x00\x00\x0f\xf8\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x07\xff\x00\x01\xff\xe0\x00\x00\x01\xff\xfa7\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Sleep=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x03\xff\xc0\x03\xf0\x00\x00\x00\x07\xef\xc0\x07\xf0\x00\x00\x00\x00\xef\xe0\x07\xe0\x00\x00\x00\x01\xc7\xe0\x0f\xe0\x00\x00\x00\x07\xa7\xf0\x0f\xc0\x00\x00\x00\x07\xe3\xf0\x1f\x80\x00\x00\x00\xf3C\xf8\x1f\x80\x00\x00\x01\xf8\x01\xf8\x1f\x80\x00\x00\x00p\x01\xf8\x1f\x80\x00\x00\x00\xe0\x00\xf8?\x00\x00\x00\x01\xf8\x00\xfc?\x00\x00\x00\x00\xf0\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc>\x03\xff\xe0\x07\xaf\xc0\xfc?\x03\xff\xe0\x07\xff\xc0\xfc?\x03\xff\xe0\x07\xff\xc0|?\x01\xff\x80\x03\xff\x80\xfc>\x00\x00\x00\x00\x10\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x80\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x01@\x00\x01\xf8\x1f\xc0\x00\x1f\xf8\x00\x03\xf8\x0f\xc0\x00\x7f\xfe\x00\x03\xf0\x0f\xe0\x00\xff\xff\x00\x03\xf0\x07\xe0\x01\xff\xff\x80\x07\xe0\x07\xf0\x01\xff\xff\x80\x0f\xe0\x03\xf0\x03\xff\xff\xc0\x0f\xc0\x03\xf8\x03\xff\xff\xc0?\xc0\x01\xfc\x01\xff\xff\x80?\x80\x00\xfe\x01\xff\xff\x80\x7f\x80\x00\xff\x00|\x00\x00\xff\x00\x00\x7f\x80x\x00\x01\xfe\x00\x00?\xe0<\x00\x07\xfc\x00\x00\x1f\xf88\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x03\xff\xfd\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Small_heart=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\xe0\x07\xf8\x00\x00\x00\x00\x7f\xf8\x1f\xfe\x00\x00\x00\x00\xff\xfe?\xff\x00\x00\x00\x01\xff\xff\x7f\xff\x80\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x1f\xff\xff\xf8\x00\x00\x00\x00\x0f\xff\xff\xe0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xff\x00\x00\x00\x00\x00\x00\x7f\xff\x00\x00\x00\x00\x00\x00\x7f\xfc\x00\x00\x00\x00\x00\x00\x1f\xf8\x00\x00\x00\x00\x00\x00\x0f\xf8\x00\x00\x00\x00\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Small_paper=b'P4\n32\n32\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x1f\x1e\x00\x00;\xbf\x00\x001\xf3\x00\x00q\xe1\x80\x00a\xc3\xa0\x00a\x83\xf0\x1fa\x87\xf8?\xe1\x87\x181\xe0\x0e\x180\xe0\x1c80`\x08p\x18 \x00\xe0\x1c\x00\x01\xf0\x0e\x00\x03\xf8\x06\x00\x01\x1c\x06\x00\x00\x0c\x06\x00\x00\x1c\x06\x00\x00\xf8\x0e\x00\x1f\xf0\x06\x00\x1f\x80\x06\x000\x00\x07\x00p\x00\x03\x80\xe0\x00\x01\xc3\xc0\x00\x00\xff\x00\x00\x00>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Small_rock=b'P4\n32\n32\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00?\xf8\x00\x00\x7f\x9c\x00\x00\xe3\x0f\xe0\x03\xc6\x1f\xf0\x07\xc6p8\x0e\xc6`\x18\x0c\xc2@\x1c\x18\xc3@\x0c\x18c\xe3\x0c\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf0\x0f\xc0\x0e\x00\x000\x03\xf8\x0f\xe0\x0f\x00\x00x\x07\xe0\x07\xe0\x1f\x00\x00\xf0\x07\xf0\x07\xf0\x0f\x00\x00\xf0\x0f\xe0\x03\xf0\x07\x80\x01\xf0\x0f\xc0\x03\xf8\x07\xc0\x03\xe0\x1f\xc0\x01\xfc\x07\xe0\x07\xe0?\x80\x01\xfe\x03\xfc\x1f\xc0\x7f\x80\x00\xff\x01\xff\xff\x80\xff\x00\x00\x7f\xc0\xff\xfe\x03\xfe\x00\x00?\xe0?\xfc\x07\xfc\x00\x00\x1f\xf0\x0f\xf0\x1f\xf8\x00\x00\x0f\xfe\x00\x00?\xf0\x00\x00\x07\xff\xc0\x03\xff\xe0\x00\x00\x03\xff\xff\x7f\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Surprise=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x1f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x10\x00\x00\x10\x03\xf0\x1f\xc0>\x00\x00|\x01\xf8\x1f\x80\x7f\x00\x00~\x01\xf8\x1f\x80\xff\x00\x00\xff\x01\xf8\x1f\x80\xff\x80\x01\xff\x00\xf8?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc>\x00\x7f\x00\x00\xff\x00\xfc?\x00~\x00\x00~\x00|?\x00>\x00\x008\x00\xfc>\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x03\xc0\x00\x01\xf8\x1f\x80\x00\x07\xe0\x00\x01\xf8\x1f\xc0\x00\x0f\xf0\x00\x01\xf8\x0f\xc0\x00\x0f\xf0\x00\x03\xf0\x0f\xe0\x00\x0f\xf0\x00\x07\xf0\x07\xe0\x00\x0f\xf8\x00\x07\xe0\x07\xf0\x00\x1f\xf0\x00\x0f\xe0\x03\xf8\x00\x0f\xf8\x00\x0f\xc0\x03\xf8\x00\x0f\xf0\x00\x1f\xc0\x01\xfc\x00\x0f\xf0\x00?\x80\x00\xfe\x00\x0f\xe0\x00\x7f\x80\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\xc0\x03\xc0\x03\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00/\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Wonderful=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x02\x00\xff\xff\xff\xff\x00\x00\x07\x03\xff\xff\x7f\xff\xc0\x00\x07\x87\xff\x80\x03\xff\xe0\x00\x1f\xcf\xfc\x00\x00\x7f\xf0\x00\x1f\xdf\xf8\x00\x00\x1f\xf8\x00\x07?\xe0\x00\x00\x07\xfc\x00\x02\x7f\x80\x00\x00\x19\xfe\x00\x02\xff\x00\x00\x00\x1c\xff\x00\x00\xfe\x00\x00\x00>\x7f\x00\x01\xfc\x00\x00\x00\x7f?\x80\x03\xf8\x00\x00\x00\x1c\x1f\xc0\x03\xf0\x00\x00\x00\x18\x1f\xe0\x07\xf0\x00\x00\x00\x08\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xe0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0<\x00\x008\x03\xf0\x1f\x80\xff\x00\x00\xff\x01\xf8\x1f\x80\xff\x80\x01\xff\x01\xf8\x1f\x81\xff\x80\x01\xff\x81\xf8?\x83\xff\xc0\x01\xff\xc0\xfc\x1f\x01\xff\xc0\x03\xff\x80\xf8?\x03\xff\xc0\x03\xff\xc0\xfc?\x01\xff\xc0\x03\xff\x80\xfc?\x01\xff\x80\x01\xff\x80\xfc>\x00\xff\x80\x01\xff\x80|?\x00~\x00\x00\xfe\x00\xfc?\x00\x1c\x00\x008\x00\xfc>\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x01\x03\xf0\x0f\xc0\x00\x00\x00\x01\x83\xf8\x0f\xe0\x00\xff\xff\x03\xc3\xf0\x07\xe0\x00\xff\xff\x0f\xe7\xe0\x07\xf0\x00\xff\xff\x07\xcf\xe0\x03\xf0\x00\x7f\xff\x01\x9f\xc0\x03\xf8\x00\x7f\xfe\x01\x9f\xc0\x01\xfc\x00?\xfc\x00?\x80\x00\xfe\x00\x1f\xf8\x00\x7f\x80\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' diff --git a/mixly/boards/default/micropython/build/lib/eye_picture.py b/mixly/boards/default/micropython/build/lib/eye_picture.py new file mode 100644 index 00000000..0ab20db6 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/eye_picture.py @@ -0,0 +1,31 @@ +#Take the picture bytes in eye_picture.py +#--dahanzimin From the Mixly Team + +Eyes_Angry=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1e\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\x80\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\xe0\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1d\xf8\x00\x00\x07\x000\x00\x00\x00|\x7f\x1c\xfe\x00\x00\x07\x000\x00\x00\x01\xfc\x7f\x1c?\x80\x00\x07\x000\x00\x00\x07\xfc\x7f\x1c\x0f\xe0\x00\x07\x000\x00\x00\x1f\x8c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x00~\x0c\x7f\x1c\x00\xfe\x00\x07\x000\x00\x01\xf8\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x0f\xe0\x07\x000\x00\x1f\x80\x0c\x7f\x1c\x00\x07\xf8\x07\x000\x00\x7f\x00\x0c\x7f\x1c\x00\x0f\xfe\x07\x000\x01\xfc\x00\x0c\x7f\x1c\x00\x1f\xff\x87\x000\x07\xf6\x80\x0c\x7f\x1c\x00?\x9f\xe7\x000\x1f\xf2\x00\x0c\x7f\x1c\x00\xbf\xbb\xff\x000\x7f\xef\x00\x0c\x7f\x1c\x00\x7f\xfc\xff\x001\xff\xff@\x0c\x7f\x1c\x00\x7f\xfc?\x00?\xff\xff\x00\x0c\x7f\x1c\x00\x7f\xfc\x0f\x00?\xaf\xff@\x0c\x7f\x1c\x00?\xf8\x07\x00>\x0f\xff\x00\x0c\x7f\x1c\x00\xbf\xfa\x07\x008\x07\xfe\x00\x1c\x7f\x0e\x00\x1f\xf0\x0e\x008\x17\xfe\x80\x1c\x7f\x0e\x00\x0f\xe0\x0e\x00<\x03\xfc\x00<\x7f\x0f\x00\x03\x80\x1e\x00\x1c\x04\xf2\x008\x7f\x07\x80\x04 <\x00\x1e\x01\x08\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Awake=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\x00\x00\x00\x07\x000\x00\x00\x00|\x7f\x1f\xf8\x00\x00\x07\x000\x00\x00\x07\xfc\x7f\x1f\xff\xc0\x00\x07\x000\x00\x01\xff\xfc\x7f\x1c\x1f\xff\x00\x07\x000\x00?\xfe\x0c\x7f\x1c\x00\xff\xf0\x07\x000\x07\xff\xc0\x0c\x7f\x1c\x00?\xff\x87\x000\x7f\xfe\x00\x0c\x7f\x1c\x01\x7f\xff\xff\x00?\xff\xff\x00\x0c\x7f\x1c\x00~i\xff\x00?\xe1\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x0f\x00<\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\xff\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x01\x7f\xd0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00~\x00\x0c\x7f\x1c\x00@@\x07\x000\x00\x81\x00\x0c\x7f\x1c\x00\n\x00\x07\x000\x00(\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Black_eye=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00?\xff\xfc\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xff\xff\xff\x80\x7f\x00\x00\x00\x00\x00\x00\x03\xff\xff\xff\xc0\x7f\x00\x1f\xff\xfe\x00\x00\x07\xc0\x00\x03\xe0\x7f\x00\x7f\xff\xff\xc0\x00\x0f\x00\x00\x00\xf0\x7f\x01\xff\xff\xff\xf0\x00\x1e\x00\x00\x00x\x7f\x03\xfa\xaa\xab\xf8\x00\x1c\x00\x00\x008\x7f\x07\xd2U%|\x008\x00\x00\x00\x1c\x7f\x07\xad\xaa\xda\xbc\x008\x00\x00\x00\x1c\x7f\x0fRU%^\x008\x00\x00\x00\x1c\x7f\x0fm\xaa\xda\xae\x000\x00\x00\x00\x0c\x7f\x1e\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1dm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1e\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1dm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1c\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1fm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1c\x92U$\x97\x000\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00B\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x018\x80\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00\x7f\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x00\xfe`\x07\x000\x01\xfc\x80\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x01\xff\x80\x0c\x7f\x1f\xff\xff\xff\xff\x000\x05\xff\xa0\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00\xff\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x01<\x80\x0c\x7f\x1dUUUW\x000\x00B\x00\x0c\x7f\x1dT\x92UW\x000\x00\x00\x00\x0c\x7f\x1e\xabm\xaa\xaf\x000\x00\x00\x00\x0c\x7f\x1dT\x92UW\x000\x00\x00\x00\x0c\x7f\x1fKm\xaa\xaf\x000\x00\x00\x00\x0c\x7f\x0e\xb4\x92U\xae\x000\x00\x00\x00\x0c\x7f\x0fKm\xaa^\x008\x00\x00\x00\x1c\x7f\x07\xb4\x92U\xbc\x008\x00\x00\x00\x1c\x7f\x07\xcbm\xaa|\x00<\x00\x00\x00<\x7f\x03\xf4\x92K\xf8\x00\x1c\x00\x00\x008\x7f\x01\xff\xff\xff\xf0\x00\x1e\x00\x00\x00x\x7f\x00\x7f\xff\xff\xc0\x00\x0f\x80\x00\x01\xf0\x7f\x00\x1f\xff\xff\x00\x00\x07\xe0\x00\x07\xe0\x7f\x00\x00\x00\x00\x00\x00\x03\xff\xff\xff\xc0\x7f\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bottom_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\x80\x00\x07\x000\x05\x00\x00\x0c\x7f\x1c\x10\x10\x00\x07\x000 @\x00\x0c\x7f\x1c\x07\xc8\x00\x07\x000\x1f\x80\x00\x0c\x7f\x1c_\xf0\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x1f\x98\x00\x07\x001\x7fh\x00\x0c\x7f\x1c\xbf\x9a\x00\x07\x000\xfep\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c?\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c_\xf4\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x07\xc0\x00\x07\x000\x1f\x80\x00\x0c\x7f\x1c\x10\x10\x00\x07\x008 @\x00\x1c\x7f\x0e\x02\x80\x00\x0e\x008\n\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bottom_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00(\x07\x000\x00\x00P\x0c\x7f\x1c\x00\x01\x01\x07\x000\x00\x02\x04\x0c\x7f\x1c\x00\x00|\x87\x000\x00\x01\xf8\x0c\x7f\x1c\x00\x05\xff\x07\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x01\xf9\x87\x000\x00\x17\xf6\x8c\x7f\x1c\x00\x0b\xf9\xa7\x000\x00\x0f\xe7\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x03\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x05\xffG\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x00|\x07\x000\x00\x01\xf8\x0c\x7f\x1c\x00\x01\x01\x07\x008\x00\x02\x04\x1c\x7f\x0e\x00\x00(\x0e\x008\x00\x00\xa0\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Crazy_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x01\x08\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xe0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xe6\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xee\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xfe\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xfe\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x01@\x0c\x7f\x1c\x00\xe0\x00\x07\x000\x00\x08\x10\x0c\x7f\x1c\x01\x08\x00\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xda\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\x9c\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xfa\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x08\x10\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x02\x80\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Crazy_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x04 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x13\x88\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x07\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xda\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x1f\xc8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xbc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x1f\xf8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xfa\x0c\x7f\x1c\x00\xa0\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x04\x04\x00\x07\x000\x00\x13\xc8\x0c\x7f\x1c\x01\xf2\x00\x07\x000\x00\x04 \x0c\x7f\x1c\x17\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xe6\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xe6\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xfe\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x17\xfd\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x01\xf0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x04\x04\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xa0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Disappointed=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x1f\xf8\x00\x07\xfc\x00\x03\xe0\x7f\x07\x80\x00><\x00\x0f\x1e\x00\x00\xf0\x7f\x07\x00\x00|\x1c\x00\x1e\x0f\x00\x00x\x7f\x0e\x00\x00\xf8\x0e\x00\x1c\x07\x80\x008\x7f\x0e\x00\x01\xf0\x0e\x008\x03\xc0\x00\x1c\x7f\x1c\x00\x03\xe0\x07\x008\x01\xe0\x00\x1c\x7f\x1c\x00\x07\xc0\x07\x008\x00\xf0\x00\x1c\x7f\x1c\x00\x0f\x80\x07\x000\x00x\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00>\x00\x07\x000\x00\x1e\x00\x0c\x7f\x1c\x00|@\x07\x000\x00\x9f\x00\x0c\x7f\x1c\x00\xff \x07\x000\x00\x7f\x80\x0c\x7f\x1c\x01\xff\xc0\x07\x000\x00\xff\xc0\x0c\x7f\x1c\x03\xfe`\x07\x000\x05\xfd\xe0\x0c\x7f\x1c\x07\xfeh\x07\x000\x03\xf9\xf0\x0c\x7f\x1c\x0f\xff\xf0\x07\x000\x03\xff\xf8\x0c\x7f\x1c\x1f\xff\xf0\x07\x000\x0b\xff\xfc\x0c\x7f\x1c?\xff\xf0\x07\x000\x03\xff\xde\x0c\x7f\x1c}\xff\xf0\x07\x000\x0b\xff\xdf\x0c\x7f\x1c\xfa\xff\xe8\x07\x000\x03\xff\xc7\x8c\x7f\x1d\xf0\xff\xc0\x07\x000\x05\xff\xa3\xcc\x7f\x1f\xe1\x7f\xd0\x07\x000\x00\xff\x01\xfc\x7f\x1f\xc0\x1f\x00\x07\x000\x00~\x00\xfc\x7f\x1f\x80@@\x07\x000\x00\x81\x00|\x7f\x1f\x00\n\x00\x07\x000\x00(\x00<\x7f\x1e\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dizzy=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x000\x00\x07\x000\x00\xc0\x00\x0c\x7f\x1c\x00\xf0\x00\x07\x000\x03\xc0\x00\x0c\x7f\x1c\x01\xc0\x00\x07\x000\x07\x00\x00\x0c\x7f\x1c\x03\x9f\xe0\x07\x000\x0e\x7f\x80\x0c\x7f\x1c\x07<\xf8\x07\x000\x1c\xf3\xe0\x0c\x7f\x1c\x06`\x1c\x07\x000\x19\x80p\x0c\x7f\x1c\x0c\xc7\xcc\x07\x0003\x1f0\x0c\x7f\x1c\x0c\xcf\xe6\x07\x0003?\x98\x0c\x7f\x1c\r\x98v\x07\x0006a\xd8\x0c\x7f\x1c\r\x9b3\x07\x0006l\xcc\x0c\x7f\x1c\r\x9b\xb3\x07\x0006n\xcc\x0c\x7f\x1c\r\x9f\xb3\x07\x0006~\xcc\x0c\x7f\x1c\x0c\xcf6\x07\x0003<\xd8\x0c\x7f\x1c\x0e\xe0f\x07\x000;\x81\x98\x0c\x7f\x1c\x06y\xee\x07\x000\x19\xe7\xb8\x0c\x7f\x1c\x03\x1f\x8c\x07\x000\x0c~0\x0c\x7f\x1c\x03\x80\x18\x07\x000\x0e\x00`\x0c\x7f\x1c\x00\xf0p\x07\x000\x03\xc1\xc0\x0c\x7f\x1c\x00\x7f\xe0\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x0f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Down=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\n\x00\x07\x000\x00(\x00\x0c\x7f\x1c\x00@@\x07\x000\x00\x81\x00\x0c\x7f\x1c\x00\x9f\x00\x07\x000\x00~\x00\x0c\x7f\x1c\x00\x7f\xd0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x07\x000\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\x7f\xe0\x07\x008\x05\xff\xa0\x1c\x7f\x0e\x01\x7f\xd0\x0e\x008\x00\xff\x00\x1c\x7f\x0e\x00\x1f\x00\x0e\x00<\x00~\x00<\x7f\x0f\x00@@\x1e\x00\x1c\x00\x81\x008\x7f\x07\x80\x15\x00<\x00\x1e\x00\x14\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Evil=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x0f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\xf0\x00\x00<\x00\x0f\x00\x00\x03\xf0\x7f\x07\xf8\x00\x00\x1c\x00\x1e\x00\x00\x07\xf8\x7f\x0e<\x00\x00\x0e\x00\x1c\x00\x00\x0e8\x7f\x0e\x1e\x00\x00\x0e\x008\x00\x00<\x1c\x7f\x1c\x0f\x00\x00\x07\x008\x00\x00x\x1c\x7f\x1c\x07\x80\x00\x07\x008\x00\x00\xf0\x1c\x7f\x1c\x01\xe0\x00\x07\x000\x00\x01\xe0\x0c\x7f\x1c\x00\xf0\x00\x07\x000\x00\x03\xc0\x0c\x7f\x1c\x00x\x00\x07\x000\x00\x07\x80\x0c\x7f\x1c\x00<\x00\x07\x000\x00\x0e\x00\x0c\x7f\x1c\x00\x1e\x00\x07\x000\x00>\x00\x0c\x7f\x1c\x00O\x00\x07\x000\x00|\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x7f\xe0\x07\x000\x01\xfd\xa0\x0c\x7f\x1c\x00\xfe\xf0\x07\x000\x03\xfc\x80\x0c\x7f\x1c\x02\xfe\xf8\x07\x000\x07\xfb\xc0\x0c\x7f\x1c\x01\xff\xfc\x07\x000\x1f\xff\xd0\x0c\x7f\x1c\x01\xff\xfe\x07\x000?\xff\xc0\x0c\x7f\x1c\x01\xff\xff\x07\x000\x7f\xff\xd0\x0c\x7f\x1c\x00\xff\xe3\xc7\x000\xf3\xff\xc0\x0c\x7f\x1c\x02\xff\xe9\xe7\x001\xe1\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\xf7\x003\xc5\xff\xa0\x0c\x7f\x1c\x00?\x80\x7f\x00?\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00?\x00>\x01<\x80\x0c\x7f\x1c\x00\x10\x80\x1f\x00<\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hurt=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x0f\x008\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00?\x00>\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\xff\x00?\x80\x00\x00\x0c\x7f\x1c\x00\x00\x03\xff\x00?\xe0\x00\x00\x0c\x7f\x1c\x00\x00\x0f\xe7\x001\xf8\x00\x00\x0c\x7f\x1c\x00\x00?\x87\x000~\x00\x00\x0c\x7f\x1c\x00\x00\xfe\x07\x000\x1f\x80\x00\x0c\x7f\x1c\x00\x03\xf8\x07\x000\x07\xe0\x00\x0c\x7f\x1c\x00\x0f\xf0\x07\x000\x03\xf8\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x04\xfe\x00\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\x80\x0c\x7f\x1c\x03\xff\xf0\x07\x000\x17\xff\xe0\x0c\x7f\x1c\x0f\xff\x98\x07\x000\x07\xf3\xf8\x0c\x7f\x1c?\xbf\xba\x07\x000\x0f\xef~\x0c\x7f\x1c\xff\x7f\xfc\x07\x000/\xff_\x8c\x7f\x1d\xf8\x7f\xfc\x07\x000\x0f\xff\x07\xec\x7f\x1f\xe0\x7f\xfc\x07\x000/\xffA\xfc\x7f\x1f\x80?\xf8\x07\x000\x0f\xff\x00|\x7f\x1e\x00\xbf\xfa\x07\x008\x07\xfe\x00\x1c\x7f\x0e\x00\x1f\xf0\x0e\x008\x17\xfe\x80\x1c\x7f\x0e\x00\x0f\xe0\x0e\x00<\x03\xfc\x00<\x7f\x0f\x00\x03\x80\x1e\x00\x1c\x04\xf2\x008\x7f\x07\x80\x04 <\x00\x1e\x01\x08\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Knocked_out=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x0f\xff\xfe\x07\x000\x1f\xff\xf8\x0c\x7f\x1c\x0f\xff\xfe\x07\x000?\xff\xfc\x0c\x7f\x1c\x0f\xff\xfe\x07\x000?\xff\xf8\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Love=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xe0\xfc\x07\x000\x0f\x81\xf0\x0c\x7f\x1c\x0f\xd1\xfa\x07\x000\x1fC\xf8\x0c\x7f\x1c\x1f\xeb\xfd\x07\x000?\xa7\xf4\x0c\x7f\x1c\x1f\xff\xfd\x07\x000\x7f\xff\xfa\x0c\x7f\x1c?\xff\xfe\x07\x000\x7f\xff\xfa\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000?\xff\xfc\x0c\x7f\x1c\x0f\xff\xfe\x07\x000\x1f\xff\xf8\x0c\x7f\x1c\x03\xff\xf8\x07\x000\x0f\xff\xf0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x07\xff\xe0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00~\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x04\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Middle_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x08@\x00\x07\x000 \x80\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000\x07 \x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000?\x80\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c?\x98\x00\x07\x000\x7f \x00\x0c\x7f\x1c\xbf\xba\x00\x07\x002\xfe\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c?\xf8\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\x7f\xe0\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000O \x00\x0c\x7f\x1c\x08@\x00\x07\x000\x10\x80\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Middle_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x84\x07\x000\x00\x02\x08\x0c\x7f\x1c\x00\x008\x07\x000\x00\x00r\x0c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x03\xf8\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x03\xf9\x87\x000\x00\x07\xf2\x0c\x7f\x1c\x00\x0b\xfb\xa7\x000\x00\x0f\xef\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xff\x0c\x7f\x1c\x00\x03\xff\x87\x000\x00\x0f\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x07\xfe\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x008\x07\x000\x00\x04\xf2\x0c\x7f\x1c\x00\x00\x84\x07\x000\x00\x01\x08\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Neutral=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x82\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x1c\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xfe\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00\xfe`\x07\x000\x01\xfc\x80\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x01<\x80\x0c\x7f\x1c\x00!\x00\x07\x000\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Nuclear=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x1e\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\xf3\xc0\x07\x000\x01\xe7\x80\x0c\x7f\x1c\x03\x800\x07\x000\x07\x00`\x0c\x7f\x1c\x06\x00\x08\x07\x000\x0c\x00\x10\x0c\x7f\x1c\r\x80$\x07\x000\x1b\x00H\x0c\x7f\x1c\x1b\x80r\x07\x0007\x00\xe4\x0c\x7f\x1c\x13\xc0\xfb\x07\x000'\x81\xf6\x0c\x7f\x1c7\xe0\xfd\x07\x000o\xc1\xfa\x0c\x7f\x1c/\xe1\xfd\x87\x000_\xc3\xfb\x0c\x7f\x1c/\xe1\xfc\x87\x000_\xc3\xf9\x0c\x7f\x1co\xe4\xfe\x87\x000\xdf\xc9\xfd\x0c\x7f\x1cO\xce\xfe\x87\x000\x9f\x9d\xfd\x0c\x7f\x1c@\x1e\x00\x87\x000\x80<\x01\x0c\x7f\x1c@\x0c\x00\x87\x000\x80\x18\x01\x0c\x7f\x1c \x00\x00\x87\x000@\x00\x01\x0c\x7f\x1c \x0e\x00\x87\x000@\x1c\x01\x0c\x7f\x1c \x1f\x01\x87\x000@>\x03\x0c\x7f\x1c\x10?\x01\x07\x000 ~\x02\x0c\x7f\x1c\x18?\x82\x07\x0000\x7f\x04\x0c\x7f\x1c\x08\x7f\x86\x07\x000\x10\xff\x0c\x0c\x7f\x1c\x04\x7f\xcc\x07\x000\x08\xff\x98\x0c\x7f\x1c\x03\x1e\x18\x07\x000\x06<0\x0c\x7f\x1c\x01\xc0`\x07\x000\x03\x80\xc0\x0c\x7f\x1c\x00\x7f\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" +Pinch_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1d\x7f\xbd\x00\x07\x00:\xfe\xfc\x00\x1c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c?\xf8\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\x7f\xe0\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x000\x7f\xe8\x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000\xbf\xd0\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000\x0f\x00\x00\x0c\x7f\x1c\x18`\x00\x07\x0000\xc0\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Pinch_middle=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x05\xfe\xf4\x07\x008\x0b\xfb\xf0\x1c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x02\xff@\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00a\x80\x07\x000\x00\xc3\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Pinch_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x17\xfb\xd7\x008\x00/\xef\\\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xff\x0c\x7f\x1c\x00\x03\xff\x87\x000\x00\x0f\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x07\xfe\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x07\xfe\x8c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x0b\xfd\x0c\x7f\x1c\x00\x008\x07\x000\x00\x00\xf0\x0c\x7f\x1c\x00\x01C\x07\x000\x00\x03\x0c\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tear=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1e\x00\x00\x00\x0f\x008\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\xbf\xa0\x07\x008\x02\xfe@\x1c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x07\x000\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x000\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\xf8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xf6\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfa\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tired_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\xbf\xba\x00\x07\x00:\xfet\x00\x1c\x7f\x1c\x7f\xf8\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x1f\xf8\x00\x07\x009\x7f\xe8\x00\x1c\x7f\x0e_\xf4\x00\x0e\x008?\xc0\x00\x1c\x7f\x0e\x07\xc0\x00\x0e\x00<\x1f\x80\x00<\x7f\x0f\x10\x10\x00\x1e\x00\x1c @\x008\x7f\x07\x85@\x00<\x00\x1e\x05\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tired_middle=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x02\xff\xe8\x07\x008\x0b\xfb\xd0\x1c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x008\x05\xff\xa0\x1c\x7f\x0e\x00?\x80\x0e\x008\x00\xff\x00\x1c\x7f\x0e\x00\x0e\x00\x0e\x00<\x01<\x80<\x7f\x0f\x00!\x00\x1e\x00\x1c\x00B\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tired_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x0b\xfb\xa7\x008\x00/\xe7\\\x7f\x1c\x00\x07\xff\x87\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x01\xff\x87\x008\x00\x17\xfe\x9c\x7f\x0e\x00\x05\xffN\x008\x00\x03\xfc\x1c\x7f\x0e\x00\x00|\x0e\x00<\x00\x01\xf8<\x7f\x0f\x00\x01\x01\x1e\x00\x1c\x00\x02\x048\x7f\x07\x80\x00(<\x00\x1e\x00\x00Px\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Toxic=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x008\x00\x0c\x7f\x1c\x00\x7f@\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\x00\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\x80\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xc4p\x07\x000\x03\x18\xc0\x0c\x7f\x1c\x01\xc4p\x07\x000\x03\x08\xc0\x0c\x7f\x1c\x00\xce`\x07\x000\x03\x99\xc0\x0c\x7f\x1c\x00\xf9\xe0\x07\x000\x01\xe7\x80\x0c\x7f\x1c\x00y\xc0\x07\x000\x00\xe7\x00\x0c\x7f\x1c\x04\x1f\x02\x07\x000\x18>\x0c\x0c\x7f\x1c\x0f\x8a\x1e\x07\x000?\x10<\x0c\x7f\x1c\x0c\xf0\xf3\x07\x0003\xe1\xec\x0c\x7f\x1c\x00>@\x07\x000\x00|\x00\x0c\x7f\x1c\r\xe3\xe6\x07\x000\x1b\xcf\xc8\x0c\x7f\x1c\x0f\xc0\xfe\x07\x000\x1f\x81\xfc\x0c\x7f\x1c\x06\x00\x0e\x07\x000\x0c\x008\x0c\x7f\x1c\x06\x00\x0c\x07\x000\x08\x00\x18\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Up=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00!\x00\x1c\x00\x1e\x00\x82\x00x\x7f\x0e\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x808\x7f\x0e\x00?\x80\x0e\x008\x00\xfe\x00\x1c\x7f\x1c\x00\x7f\xc0\x07\x008\x05\xff\xa0\x1c\x7f\x1c\x00\xfe`\x07\x008\x01\xfc\x80\x1c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x01<\x80\x0c\x7f\x1c\x00!\x00\x07\x000\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Winking=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x00\x00\x00\x0c\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x00\xff\xe0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' diff --git a/mixly/boards/default/micropython/build/lib/gnss.py b/mixly/boards/default/micropython/build/lib/gnss.py new file mode 100644 index 00000000..39484a02 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/gnss.py @@ -0,0 +1,91 @@ +""" +GNSS + +Micropython library for the GNSS(NMEA0183/GPS,DBS) +======================================================= +@dahanzimin From the Mixly Team +""" +from time import sleep_ms +from ubinascii import unhexlify + +class NMEA0183: + def __init__(self, uart, baudrate=9600, timeout=200): + self._uart=uart + self._uart.init(baudrate=baudrate, timeout=timeout, rxbuf=1024) + self.time=[None, None, None, None, None, None] + self.locate=['', None, '', None, None, None, None] #0'1经度,2'3纬度,4海拔m,5速度m/s,6航向° + self.status=[False, ' ', 0] #有效标注,定位模式,卫星量 + if not self._chip_id(): + raise AttributeError("Cannot find a GNSS device") + + def _crc8(self, buffer): + '''对数据进行CRC校验''' + crc = 0x00 + for byte in buffer: + crc ^= byte + return crc & 0xff + + def _chip_id(self): + for _ in range(10): + sleep_ms(300) + if self.any(): + self._uart.write(("$PCAS02,1000*2E\r\n").encode()) #更新频率1HZ + self._uart.write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n".encode()) #只加载GNGGA和GNRMC + return True + + def _judge(self, buffer, dlen): + try: + data=buffer.strip().decode().split(',') + if len(data) == dlen: + if unhexlify(data[-1][-2:])[0] == self._crc8(buffer[1:-5]): + return True,data + return False,None + except : + return False,None + + def any(self): + flag_rmc,flag_gga=False,False + while self._uart.any(): + _data=self._uart.readline() + if b'$GNGGA' in _data: + flag_gga,data=self._judge(_data, 15) + #print("GGA----",flag_gga) + if flag_gga: + self.time[3]= int(data[1][0:2]) if data[1] else None + self.time[4]= int(data[1][2:4]) if data[1] else None + self.time[5]= int(data[1][4:6]) if data[1] else None + self.locate[0]= data[5] + self.locate[1]= int(data[4][:3])+int(data[4][3:].replace('.',''))/6000000 if data[4] else None + self.locate[2]= data[3] + self.locate[3]= int(data[2][:2])+int(data[2][2:].replace('.',''))/6000000 if data[2] else None + self.locate[4]= float(data[9]) if data[3] else None + self.status[0]= False if '0' in data[6] else True + self.status[2]= int(data[7]) + if b'$GNRMC' in _data: + flag_rmc,data=self._judge(_data, 14) + #print("RMC----",flag_rmc) + if flag_rmc: + self.time[0]= int(data[9][4:6])+2000 if data[9] else None + self.time[1]= int(data[9][2:4]) if data[9] else None + self.time[2]= int(data[9][0:2]) if data[9] else None + self.time[3]= int(data[1][0:2])+8 if data[1] else None + self.time[4]= int(data[1][2:4]) if data[1] else None + self.time[5]= int(data[1][4:6]) if data[1] else None + self.locate[0]= data[6] + self.locate[1]= int(data[5][:3])+int(data[5][3:].replace('.',''))/6000000 if data[5] else None + self.locate[2]= data[4] + self.locate[3]= int(data[3][:2])+int(data[3][2:].replace('.',''))/6000000 if data[3] else None + self.locate[5]= round(float(data[7])*0.514, 2) if data[7] else None + self.locate[6]= float(data[8]) if data[8] else None + self.status[0]= False if 'V' in data[2] else True + self.status[1]= data[12] + return flag_rmc | flag_gga + + def time(self): + return tuple(self.time) + + def locate(self): + return tuple(self.locate) + + def status(self): + return tuple(self.status) diff --git a/mixly/boards/default/micropython/build/lib/hmac.py b/mixly/boards/default/micropython/build/lib/hmac.py new file mode 100644 index 00000000..dbbdd471 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/hmac.py @@ -0,0 +1,87 @@ +# Implements the hmac module from the Python standard library. + + +class HMAC: + def __init__(self, key, msg=None, digestmod=None): + if not isinstance(key, (bytes, bytearray)): + raise TypeError("key: expected bytes/bytearray") + + import hashlib + + if digestmod is None: + # TODO: Default hash algorithm is now deprecated. + digestmod = hashlib.md5 + + if callable(digestmod): + # A hashlib constructor returning a new hash object. + make_hash = digestmod # A + elif isinstance(digestmod, str): + # A hash name suitable for hashlib.new(). + make_hash = lambda d=b"": getattr(hashlib, digestmod)(d) + else: + # A module supporting PEP 247. + make_hash = digestmod.new # C + + self._outer = make_hash() + self._inner = make_hash() + + self.digest_size = getattr(self._inner, "digest_size", None) + # If the provided hash doesn't support block_size (e.g. built-in + # hashlib), 64 is the correct default for all built-in hash + # functions (md5, sha1, sha256). + self.block_size = getattr(self._inner, "block_size", 64) + + # Truncate to digest_size if greater than block_size. + if len(key) > self.block_size: + key = make_hash(key).digest() + + # Pad to block size. + key = key + bytes(self.block_size - len(key)) + + self._outer.update(bytes(x ^ 0x5C for x in key)) + self._inner.update(bytes(x ^ 0x36 for x in key)) + + if msg is not None: + self.update(msg) + + @property + def name(self): + return "hmac-" + getattr(self._inner, "name", type(self._inner).__name__) + + def update(self, msg): + self._inner.update(msg) + + def copy(self): + if not hasattr(self._inner, "copy"): + # Not supported for built-in hash functions. + raise NotImplementedError() + # Call __new__ directly to avoid the expensive __init__. + other = self.__class__.__new__(self.__class__) + other.block_size = self.block_size + other.digest_size = self.digest_size + other._inner = self._inner.copy() + other._outer = self._outer.copy() + return other + + def _current(self): + h = self._outer + if hasattr(h, "copy"): + # built-in hash functions don't support this, and as a result, + # digest() will finalise the hmac and further calls to + # update/digest will fail. + h = h.copy() + h.update(self._inner.digest()) + return h + + def digest(self): + h = self._current() + return h.digest() + + def hexdigest(self): + import binascii + + return str(binascii.hexlify(self.digest()), "utf-8") + + +def new(key, msg=None, digestmod=None): + return HMAC(key, msg, digestmod) diff --git a/mixly/boards/default/micropython/build/lib/hp203x.py b/mixly/boards/default/micropython/build/lib/hp203x.py new file mode 100644 index 00000000..41ee5e7e --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/hp203x.py @@ -0,0 +1,88 @@ +""" +HP203X + +MicroPython library for the HP203X(Air pressure sensor) +======================================================= + +#Changed from circuitpython to micropython 20220211 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +HP203X_ADDRESS = const(0x76) +HP203X_REG_RST = const(0x06) +HP203X_REG_RDY = const(0x0D) +HP20X_READ_P = const(0x30) +HP20X_READ_H = const(0x31) +HP20X_READ_T = const(0x32) +HP20X_READ_CAL = const(0x28) +HP20X_WR_CONVERT_CMD = const(0x40) + +#转换时间 越大时间越久 +#HP20X_CONVERT_OSR4096 =0<<2 +HP20X_CONVERT_OSR2048 =1<<2 +#HP20X_CONVERT_OSR1024 =2<<2 +#HP20X_CONVERT_OSR512 =3<<2 +#HP20X_CONVERT_OSR256 =4<<2 +#HP20X_CONVERT_OSR128 =5<<2 + +class HP203X: + def __init__(self, i2c_bus,cal=False): + self._device = i2c_bus + self._address = HP203X_ADDRESS + self.data_reg = bytearray(3) + self._buffer = bytearray(1) + self.osr = HP20X_CONVERT_OSR2048 #SET time + + if self._read_rdy()&0x40 ==0: + raise AttributeError("Cannot find a HP203X") + + self._rst() #Reset + time.sleep(0.1) + if cal: #Calibration + self._write_cmd(HP20X_WR_CONVERT_CMD|self.osr) + time.sleep(0.1) + self._calibration() + print("calibration") + + def _read_data(self, address): + self._buffer[0] = address & 0xFF + self._device.writeto(self._address,self._buffer) + self._device.readfrom_into(self._address,self.data_reg) + return self.data_reg + + def _write_cmd(self,command): + self._buffer[0] = command & 0xFF + self._device.writeto(self._address,self._buffer) + + def _read_rdy(self): + return self._read_data(HP203X_REG_RDY)[0] + + def _calibration(self): + self._write_cmd(HP20X_READ_CAL) + + def _rst(self): + self._write_cmd(HP203X_REG_RST) + + def u2s(self,n): + return n if n < (1 << 23) else n - (1 << 24) + + def get_data(self,flag): + self._write_cmd(HP20X_WR_CONVERT_CMD|self.osr) + time.sleep(0.1) + self._read_data(flag) + hp_data=(self.data_reg[0]<<16)|(self.data_reg[1]<<8)|self.data_reg[2] + return self.u2s(hp_data)/100 + + def pressure(self): + return self.get_data(HP20X_READ_P) + + def altitude(self): + return self.get_data(HP20X_READ_H) + + def temperature(self): + return self.get_data(HP20X_READ_T) diff --git a/mixly/boards/default/micropython/build/lib/ht16k33.py b/mixly/boards/default/micropython/build/lib/ht16k33.py new file mode 100644 index 00000000..056aecfb --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ht16k33.py @@ -0,0 +1,59 @@ +""" +HT16K33-framebuf + +Micropython library for the HT16K33 Matrix16x8 +======================================================= + +#Preliminary composition 20230411 + +@dahanzimin From the Mixly Team +""" +import uframebuf +from micropython import const + +_HT16K33_BLINK_CMD = const(0x80) +_HT16K33_BLINK_DISPLAYON = const(0x01) +_HT16K33_CMD_BRIGHTNESS = const(0xE0) +_HT16K33_OSCILATOR_ON = const(0x21) + +class HT16K33(uframebuf.FrameBuffer_Ascall): + def __init__(self, i2c, address=0x70, brightness=0.3, width=16, height=8): + self._i2c = i2c + self._address = address + self._blink_rate=0 + self._brightness=brightness + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_HMSB) + self._write_cmd(_HT16K33_OSCILATOR_ON) + self.blink_rate(0) + self.set_brightness(brightness) + self.fill(0) + self.show() + + def _write_cmd(self, val): + '''I2C write command''' + self._i2c.writeto(self._address,val.to_bytes(1, 'little')) + + def blink_rate(self, rate=None): + if rate is None: + return self._blink_rate + if not 0 <= rate <= 3: + raise ValueError("Blink rate must be an integer in the range: 0-3") + rate = rate & 0x03 + self._blink_rate = rate + self._write_cmd(_HT16K33_BLINK_CMD | _HT16K33_BLINK_DISPLAYON | rate << 1) + + def get_brightness(self): + return self._brightness + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0-1.0") + self._brightness = brightness + xbright = round(15 * brightness) + xbright = xbright & 0x0F + self._write_cmd(_HT16K33_CMD_BRIGHTNESS | xbright) + + def show(self): + """Refresh the display and show the changes.""" + self._i2c.writeto_mem(self._address, 0x00, self._buffer) diff --git a/mixly/boards/default/micropython/build/lib/huskylens.py b/mixly/boards/default/micropython/build/lib/huskylens.py new file mode 100644 index 00000000..4341b901 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/huskylens.py @@ -0,0 +1,305 @@ +""" +HuskyLens + +MicroPython library for the HuskyLens-I2C(DF) +======================================================= + +#Preliminary composition 20220224 +#base on https://github.com/HuskyLens/HUSKYLENSPython 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from ubinascii import unhexlify,hexlify + +commandHeaderAndAddress = "55AA11" +algorthimsByteID = { + "ALGORITHM_OBJECT_TRACKING": "0100", #物体追踪 + "ALGORITHM_FACE_RECOGNITION": "0000", #人脸识别 + "ALGORITHM_OBJECT_RECOGNITION": "0200", #物体识别 + "ALGORITHM_LINE_TRACKING": "0300", #巡线 + "ALGORITHM_COLOR_RECOGNITION": "0400", #颜色识别 + "ALGORITHM_TAG_RECOGNITION": "0500", #标签识别 + "ALGORITHM_OBJECT_CLASSIFICATION": "0600", #物体分类 + "ALGORITHM_QR_CODE_RECOGNTITION" : "0700", #二维码识别(教育版独有) + "ALGORITHM_BARCODE_RECOGNTITION":"0800", #条形码识别(教育版独有) +} + +class Arrow: + def __init__(self, xTail, yTail , xHead , yHead, ID): + self.xTarget=xTail + self.yTarget=yTail + self.xOrigin=xHead + self.yOrigin=yHead + self.id=ID + self.learned= True if ID > 0 else False + self.type="arrows" + +class Block: + def __init__(self, x, y , width , height, ID): + self.xCenter = x + self.yCenter=y + self.width=width + self.height=height + self.id=ID + self.learned= True if ID > 0 else False + self.type="blocks" + +class HuskyLens: + def __init__(self, i2c,address=0x32): + self._address = address + self.checkOnceAgain=True + self._device = i2c + self._buffer=[] + self._learned_number=0 + if not self.knock(): + raise AttributeError("Cannot find a HuskyLens") + + def _write_cmd(self, cmd): + '''Write memory address''' + self._device.writeto(self._address, unhexlify(cmd)) + + def _read_cmd(self, nbytes): + '''Read memory address''' + return self._device.readfrom(self._address, nbytes) + + def _checksum(self, hexStr): + '''data checksums''' + total = 0 + for i in range(0, len(hexStr), 2): + total += int(hexStr[i:i+2], 16) + hexStr = hex(total)[-2:] + return hexStr + + def _read_data(self): + '''Read data''' + while True: + time.sleep(0.01) + buffer = self._read_cmd(5) + if buffer[0] == 0x55: + break + buffer += self._read_cmd(int(buffer[3])+1) + strs=hexlify(buffer).decode() + + headers = strs[0:4] + address = strs[4:6] + data_length = int(strs[6:8], 16) + command = strs[8:10] + if(data_length > 0): + data = strs[10:10+data_length*2] + else: + data = '' + checkSum = strs[2*(6+data_length-1):2*(6+data_length-1)+2] + return [headers, address, data_length, command, data, checkSum] + + def getBlockOrArrowCommand(self): + commandSplit = self._read_data() + isBlock = True if commandSplit[3] == "2a" else False + return (commandSplit[4],isBlock) + + def processReturnData(self): + inProduction = True + byteString="" + if inProduction : + commandSplit = self._read_data() + + if commandSplit[3] == "2e": + return "Knock Recieved" + else: + returnData = [] + numberOfBlocksOrArrow = int(commandSplit[4][2:4]+commandSplit[4][0:2], 16) + self._learned_number = int(commandSplit[4][6:8]+commandSplit[4][4:6], 16) + + for i in range(numberOfBlocksOrArrow): + tmpObj=self.getBlockOrArrowCommand() + isBlock=tmpObj[1] + returnData.append(tmpObj[0]) + + if returnData : + finalData = [] + tmp = [] + for i in returnData: + tmp = [] + for q in range(0, len(i), 4): + low=int(i[q:q+2], 16) + high=int(i[q+2:q+4], 16) + if(high>0): + val=low+255+high + else: + val=low + tmp.append(val) + finalData.append(tmp) + tmp = [] + self.checkOnceAgain=True + self._buffer=self.convert_to_class_object(finalData,isBlock) + return "Data processing completed" + else: + self._buffer=[] + + def convert_to_class_object(self,data,isBlock): + tmp=[] + for i in data: + if(isBlock): + obj = Block(i[0],i[1],i[2],i[3],i[4]) + else: + obj = Arrow(i[0],i[1],i[2],i[3],i[4]) + tmp.append(obj) + return tmp + + def knock(self): + '''Send a simple knock to the HuskyLens to ensure that you are connected and can communicate.''' + self._write_cmd(commandHeaderAndAddress+"002c3c") + return self._read_data()[3] == "2e" + + def command_request_algorthim(self, alg): + '''切换xx算法''' + if alg in algorthimsByteID: + cmd = commandHeaderAndAddress+"022d"+algorthimsByteID[alg] + cmd += self._checksum(cmd) + self._write_cmd(cmd) + return self.processReturnData() + else: + print("INCORRECT ALGORITHIM NAME") + + def command_request(self): + '''请求一次数据 存入结果''' + self._write_cmd(commandHeaderAndAddress+"002030") + self.processReturnData() + + def read_learned_id_count(self): + '''从结果中获取 已学习ID总数''' + return self._learned_number + + def is_appear_direct(self,shape): + '''从结果中获取 方块或箭头 是否在画面中''' + if len(self._buffer) > 0: + return self._buffer[0].type == shape + + + def read_block_center_parameter_direct(self,shape): + '''从结果中获取靠近中心 方块或箭头 的信息''' + if len(self._buffer) > 0: + if self._buffer[0].type == shape : + return self._buffer[0] + else : + return False + + def is_learned(self,get_id): + '''从结果中获取获取IDx是否已学习''' + if 0 < get_id < self._learned_number: + return True + else: + return False + + def is_appear(self,get_id,shape): + '''从结果中获取获取IDx 方块或箭头 是否在画面中''' + if len(self._buffer) > 0: + for i in self._buffer : + if i.id == get_id : + return i.type == shape + + def read_blocks_arrows_parameter(self,get_id,number,shape): + '''从结果中获取获取IDx 第number个方块或箭头 的信息''' + if len(self._buffer) > 0: + id_list=[] + for i in self._buffer : + if i.id == get_id and i.type == shape: + id_list.append(i) + if number is None: + return id_list[0] + else: + return id_list[number-1] + + def read_count(self,get_id,shape): + '''从结果中获取获取IDx 方块或箭头 的总数''' + num=0 + if len(self._buffer) > 0: + for i in self._buffer : + if get_id is None and i.type == shape: + num+=1 + if i.id == get_id and i.type == shape: + num+=1 + return num + + def read_blocks_arrows_parameter_direct(self,number,shape): + '''从结果中获取获取第x个 方块或箭头 的信息''' + if len(self._buffer) >= number : + print(len(self._buffer)) + if self._buffer[number-1].type == shape : + return self._buffer[number-1] + + def command_request_learn_once(self,get_id): + '''自动学习一次 IDx''' + data = "{:04x}".format(get_id) + part1=data[2:] + part2=data[0:2] + #reverse to correct endiness + data=part1+part2 + dataLen = "{:02x}".format(len(data)//2) + cmd = commandHeaderAndAddress+dataLen+"36"+data + print("-----",cmd) + cmd += self._checksum(cmd) + self._write_cmd(cmd) + + def command_request_forget(self): + '''遗忘当前算法的所有学习数据''' + self._write_cmd(commandHeaderAndAddress+"003747") + + def command_request_customnames(self,name,get_id): + '''设置当前算法 IDx 名字为 name''' + nameDataSize = "{:02x}".format(len(name)+1) + name = hexlify(name).decode()+"00" + localId = "{:02x}".format(get_id) + data = localId+nameDataSize+name + dataLen = "{:02x}".format(len(data)//2) + cmd = commandHeaderAndAddress+dataLen+"2f"+data + cmd += self._checksum(cmd) + self._write_cmd(cmd) + + def command_request_custom_text(self,name,x,y): + '''屏幕叠加显示文字name 在 xy''' + name=hexlify(name).decode() + nameDataSize = "{:02x}".format(len(name)//2) + if x>255: + x="ff"+"{:02x}".format(x%255) + else: + x="00"+"{:02x}".format(x) + y="{:02x}".format(y) + data = nameDataSize+x+y+name + dataLen = "{:02x}".format(len(data)//2) + cmd = commandHeaderAndAddress+dataLen+"34"+data + cmd += self._checksum(cmd) + self._write_cmd(cmd) + + def command_request_clear_text(self): + '''清除屏幕显示的文字''' + self._write_cmd(commandHeaderAndAddress+"003545") + + def command_request_photo(self): + '''触发拍照保存到SD卡''' + self._write_cmd(commandHeaderAndAddress+"003040") + time.sleep(0.5) + + def command_request_screenshot(self): + '''触发截屏保存到SD卡''' + self._write_cmd(commandHeaderAndAddress+"003949") + time.sleep(0.5) + + def command_request_save_model_to_SD_card(self,idVal): + '''保存当前算法数据位SD卡 (0~4) 号模型''' + idVal = "{:04x}".format(idVal) + idVal = idVal[2:]+idVal[0:2] + cmd = commandHeaderAndAddress+"0232"+idVal + cmd += self._checksum(cmd) + self._write_cmd(cmd) + time.sleep(0.5) + + def command_request_load_model_from_SD_card(self,idVal): + '''加载当前算法数据位SD卡 (0~4) 号模型''' + idVal = "{:04x}".format(idVal) + idVal = idVal[2:]+idVal[0:2] + cmd = commandHeaderAndAddress+"0233"+idVal + cmd += self._checksum(cmd) + self._write_cmd(cmd) + time.sleep(0.5) diff --git a/mixly/boards/default/micropython/build/lib/hx720.py b/mixly/boards/default/micropython/build/lib/hx720.py new file mode 100644 index 00000000..4079cdf5 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/hx720.py @@ -0,0 +1,69 @@ +""" +HX720/HX711 + +Micropython library for the HX720/HX711(Load Cell) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from machine import Pin +from micropython import const + +DATA_BITS = const(24) +READY_TIMEOUT_SEC = const(500) + +class HX720: + def __init__(self, sck_pin, dat_pin, scale=500, pulse_obj=1): + self._sck = Pin(sck_pin, Pin.OUT, value=0) + self._dat = Pin(dat_pin, Pin.IN, Pin.PULL_UP) + self._obj = min(max(pulse_obj, 1), 3) + self.scale = scale + self.tare() + + def _wait(self): + """超时响应报错""" + star = time.ticks_ms() + while not self.is_ready(): + if time.ticks_diff(time.ticks_ms(), star) > READY_TIMEOUT_SEC: + raise AttributeError("Cannot find a HX711/HX720") + + def is_ready(self): + """检查是否有数据可以读取""" + return self._dat.value() == 0 + + def set_scale(self, scale): + """设置比例因子""" + self.scale = scale + + def read_raw(self): + """读取传感器的原始数据""" + if not self.is_ready(): + self._wait() + raw_data = 0 + for _ in range(DATA_BITS): + self._sck.value(1) + self._sck.value(0) + raw_data = raw_data << 1 | self._dat.value() + + # 根据脉冲功能设置多读几次 + for _ in range(self._obj): + self._sck.value(1) + self._sck.value(0) + + return raw_data if raw_data < (1 << (DATA_BITS - 1)) else raw_data - (1 << DATA_BITS) + + def tare(self, times=10): + """清零传感器""" + _values = [] + for _ in range(max(times, 5)): + _values.append(self.read_raw()) + _values = sorted(_values)[2: -2] + self.offset = sum(_values) / len(_values) + + def read_weight(self, times=5): + """读取重量数据,返回去掉偏移量的平均值""" + _values = [] + for _ in range(max(times, 3)): + _values.append(self.read_raw()) + _values = sorted(_values)[1: -1] + return round((sum(_values) / len(_values)- self.offset) / self.scale, 2) diff --git a/mixly/boards/default/micropython/build/lib/i2cdevice.py b/mixly/boards/default/micropython/build/lib/i2cdevice.py new file mode 100644 index 00000000..66ca0b65 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/i2cdevice.py @@ -0,0 +1,280 @@ +""" +I2C_Device + +Micropython library for the I2C communication Device(TD) +======================================================= + +@dahanzimin From the Mixly Team +""" +import random +from machine import SoftI2C + +def _u2s(value, n=8): + return value if value < (1 << (n-1)) else value - (1 << n) + +'''i2c-Inheritance''' +class I2C_device(SoftI2C): + + CRC8_Table =b'\x00^\xbc\xe2a?\xdd\x83\xc2\x9c~ \xa3\xfd\x1fA\x9d\xc3!\x7f\xfc\xa2@\x1e_\x01\xe3\xbd>`\x82\xdc#}\x9f\xc1B\x1c\xfe\xa0\xe1\xbf]\x03\x80\xde> num) + elif value == -1: + self._i2c.write_device(self._addrs[naddr], 0xA0, 0x40 >> num) + except Exception as e: + raise RuntimeError("Cannot find a Traffic lights", e) + +'''LED''' +class LED(Base): + + def brightness(self, naddr=0, value=None): + '''LED灯参数 value: 亮度0~100%, None返回亮度值''' + try: + if value is None: + return self._i2c.read_device(self._addrs[naddr], 0x10) + else: + value = max(min(value, 100), 0) + self._i2c.write_device(self._addrs[naddr], 0xA0, value) + + except Exception as e: + raise RuntimeError("Cannot find a LED device", e) + +class W_LED(LED): + _addrs = [0x38, 0x39, 0x3A, 0x3B] + +class R_LED(LED): + _addrs = [0x3C, 0x3D, 0x3E, 0x3F] + +class Y_LED(LED): + _addrs = [0x40, 0x41, 0x42, 0x43] + +class G_LED(LED): + _addrs = [0x44, 0x45, 0x46, 0x47] + +class B_LED(LED): + _addrs = [0x78, 0x79, 0x7A, 0x7B] + +'''button*5''' +class Buttonx5(Base): + _addrs = [0x68, 0x69, 0x6A, 0x6B] + + def value(self, naddr=0): + '''十字按键返回 (上,下,左,右,中)/bool''' + try: + flag = self._i2c.read_device(self._addrs[naddr], 0x10) + return bool(flag >> 4 & 1), bool(flag >> 3 & 1), bool(flag >> 2 & 1), bool(flag >> 1 & 1), bool(flag & 1) + except Exception as e: + raise RuntimeError("Cannot find a Button sensor", e) + +'''button*1''' +class Button(Base): + _addrs = [0x54, 0x55, 0x56, 0x57] + + def value(self, naddr=0): + '''触碰传感器返回 数值/bool''' + try: + return bool(self._i2c.read_device(self._addrs[naddr], 0x10)) + except Exception as e: + raise RuntimeError("Cannot find a Touch sensor", e) + +'''Infrared sensor''' +class Infrared(Base): + _addrs = [0x6C, 0x6D, 0x6E, 0x6F] + + def value(self, naddr=0): + '''红外接近返回 数值0~100%''' + try: + return self._i2c.read_device(self._addrs[naddr], 0x10) + except Exception as e: + raise RuntimeError("Cannot find a Infrared sensor", e) + +'''ultrasonic sensor''' +class Sonar(Base): + _addrs = [0x24, 0x25, 0x26, 0x27] + _state = 0x00 + def value(self, naddr=0): + '''超声波测距返回 距离数值cm''' + try: + value = self._i2c.read_device(self._addrs[naddr], 0x10, 2) + return value[0] << 8 | value[1] + except Exception as e: + raise RuntimeError("Cannot find a Ultrasonic sensor", e) + + def led(self, naddr=0, num=0, value=0): + '''超声波指示灯参数 num:序号0~3,value:0灭,1亮,-1反转 ''' + try: + if value > 0: + self._state |= 1 << num + elif value < 0: + self._state ^= 1 << num + else: + self._state &= ~ (1 << num) + self._i2c.write_device(self._addrs[naddr], 0xA0, bytearray([self._state & 0xff, 0x00])) + except Exception as e: + raise RuntimeError("Cannot find a Ultrasonic sensor", e) + +'''Potentiometer''' +class Dimmer(Base): + _addrs = [0x2C, 0x2D, 0x2E, 0x2F] + + def value(self, naddr=0): + '''旋钮传感器返回 数值0~100%''' + try: + return self._i2c.read_device(self._addrs[naddr], 0x10) + except Exception as e: + raise RuntimeError("Cannot find a Potentiometer", e) + +'''Color sensor''' +class Color_ID(Base): + _id = ('Black', 'Violet', 'Unknown', 'Blue', 'Cyan', 'Green', 'Unknown', 'Yellow', 'Unknown', 'Red', 'White', 'Unknown') + _addrs = [0x20, 0x21, 0x22, 0x23] + + def recognition(self, naddr=0): + '''颜色识别返回 (颜色名,(R,G,B),环境亮度0~100,反射亮度0~100)''' + try: + color = self._i2c.read_device(self._addrs[naddr], 0x10, 6) + return self._id[min(color[0],11)], (color[1],color[2],color[3]), color[4], color[5] + except Exception as e: + raise RuntimeError("Cannot find a Color sensor", e) + +'''Laser Sensor''' +class TOF(Base): + _addrs = [0x5C, 0x5D, 0x5E, 0x5F] + + def value(self, naddr=0): + '''激光测距传感器返回 数值cm''' + try: + flag = self._i2c.read_device(self._addrs[naddr], 0x10, 2) + return (flag[0] << 8 | flag[1]) / 100 + except Exception as e: + raise RuntimeError("Cannot find a Laser Sensor", e) + + def enable(self, naddr=0, en=True): + '''激光测距传感器 en:0关闭,1打开''' + try: + self._i2c.write_device(self._addrs[naddr], 0xA0, int(en) & 0x01) + except Exception as e: + raise RuntimeError("Cannot find a Laser Sensor", e) + +'''Servo Motor''' +class Motor_servo(Base): + _addrs = [0x60, 0x61, 0x62, 0x63] + _mstop = [0, 0, 0, 0] + + def stop_mode(self, naddr=0, mode=0): + '''电机停止模式 mode:0,保持位置 1,惯性滑行 2,阻力制动''' + self._mstop[naddr] = mode + + def _write(self, naddr=0, mode=0, value=0, direction=0, angle=0, origin=0, keep=0, select=0): + '''寄存器参数设置''' + try: + _bytes1 = direction<<6 | mode<<5 | select<<4 | origin<<3 | keep<<2 | self._mstop[naddr] + _bytes2 = max(min(value, 100), 0) + _bytes3 = angle & 0xFF + _bytes4 = angle>>8 & 0xFF + _bytes5 = angle>>16 & 0xFF + self._i2c.write_device(self._addrs[naddr], 0xA0, bytearray([_bytes1, _bytes2, _bytes3, _bytes4, _bytes5])) + except Exception as e: + raise RuntimeError("Cannot find a Servo Motor", e) + + def absolute_run(self, naddr=0, mode=0, value=50, direction=0, angle=0): + ''' 绝对角度运行模式(类舵机) + 运行模式mode 0:速度模式,1:功率模式 + 模式数值value 0~100% + 转向设置direction 0:顺时针,1:最短路径,2:逆时针 + 旋转角度angle 0~360° + ''' + self._write(naddr=naddr, mode=mode, value=value, direction=direction, angle=angle, select=0) + + def relative_run(self, naddr=0, mode=0, value=50, angle=0): + ''' 相对角度运行模式(类编码电机) + 运行模式mode 0:速度模式,1:功率模式 + 模式数值value 0~100% + 旋转角度angle -8388607~8388607° + ''' + self._write(naddr=naddr, mode=mode, value=value, angle=angle, select=1) + + def relative_origin(self, naddr=0): + '''当前位置设置为原点''' + self._write(naddr=naddr, origin=1, select=1) + + def relative_continue(self, naddr=0, mode=0, value=50, direction=0): + ''' 相对角度运行模式(类普通电机) + 运行模式mode 0:速度模式,1:功率模式 + 模式数值value 0~100% + 转向设置direction 0:顺时针,2:逆时针 + ''' + self._write(naddr=naddr, mode=mode, value=value, direction=direction, keep=1, select=1) + + def stop(self, naddr=0): + '''电机停止''' + self._write(naddr=naddr, keep=1) + + def state(self,naddr=0): + '''运行状态返回 (功率, 速度, 绝对角度, 相对角度, 是否堵住, 是否转完) ''' + try: + _buf = self._i2c.read_device(self._addrs[naddr], 0x10, 7) + return _u2s(_buf[0]), _u2s(_buf[1]), (_buf[2] & 0x01)<<8 | _buf[3], _u2s((_buf[4]<<16 | _buf[5]<<8 | _buf[6]),24), bool(_buf[2] & 0x40), bool(_buf[2] & 0x80) + except Exception as e: + raise RuntimeError("Cannot find a Servo Motor", e) diff --git a/mixly/boards/default/micropython/build/lib/i2clcd.py b/mixly/boards/default/micropython/build/lib/i2clcd.py new file mode 100644 index 00000000..381f9a40 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/i2clcd.py @@ -0,0 +1,79 @@ +""" +LCD1602、LCD2004_I2C + +Micropython library for the I2C(LCD1602、LCD2004) +======================================================= + +#Preliminary composition 20221117 + +dahanzimin From the Mixly Team +""" +from time import sleep_ms +from micropython import const + +LCD_DAT = const(0x01) # Mode - Sending data +LCD_CMD = const(0x00) # Mode - Sending command +LCD_LINES = (0x80, 0xC0, 0x94, 0xD4) + +class LCD(): + def __init__(self, i2c_bus, i2c_addr=0x27, lcd_width=16): + self._device = i2c_bus + self._address = i2c_addr + self._lcd_width = lcd_width + self._backlight = True + self._last_data = 0x00 + + for i in [0x30, 0x30, 0x30,0x20]: + self._i2c_write(i) + sleep_ms(1) + for i in [0x28, 0x0C, 0x06]: + self.write_byte(i , LCD_CMD) + self.clear() + + def _i2c_write(self, data , pulse_en=True): + """write one byte to I2C bus""" + self._last_data = data + self._device.writeto(self._address,data.to_bytes(1, 'little')) + sleep_ms(0) + if pulse_en : + self._device.writeto(self._address,(data | 0b00000100).to_bytes(1, 'little')) + sleep_ms(0) + self._device.writeto(self._address,(data & ~0b00000100).to_bytes(1, 'little')) + sleep_ms(0) + + def write_byte(self, data, mode): + """write one byte to LCD""" + data_H = (data & 0xF0) | self._backlight * 0x08 | mode + data_L = ((data << 4) & 0xF0) | self._backlight * 0x08 | mode + self._i2c_write(data_H) + self._i2c_write(data_L) + + def clear(self): + """Clear the display and reset the cursor position""" + self.write_byte(0x01, LCD_CMD) + sleep_ms(1) + + def backlight(self, on_off): + """ Set whether the LCD backlight is on or off""" + self._backlight = on_off & 0x01 + i2c_data = (self._last_data & 0xF7) + self._backlight * 0x08 + self._i2c_write(i2c_data,pulse_en=False) + + def shows(self, text, line=0, column=0, center=False): + '''Character display''' + text = str(text).encode('ascii') + column=(self._lcd_width-len(text))//2 if center else column + self.write_byte(LCD_LINES[line] + column, LCD_CMD) + for b in text: + self.write_byte(0x0C+0*0x02+0*0x01, LCD_CMD) + self.write_byte(b, LCD_DAT) + + def print(self, text, line=0, column=0, delay=500): + '''Print Effect Character Display''' + text = str(text).encode('ascii') + self.write_byte(LCD_LINES[line] + column, LCD_CMD) + for b in text: + self.write_byte(0x0C+1*0x02+1*0x01, LCD_CMD) + sleep_ms(delay) + self.write_byte(b, LCD_DAT) + sleep_ms(delay) diff --git a/mixly/boards/default/micropython/build/lib/icm42670.py b/mixly/boards/default/micropython/build/lib/icm42670.py new file mode 100644 index 00000000..9d5c644a --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/icm42670.py @@ -0,0 +1,94 @@ +""" +ICM42670P + +Micropython library for the ICM42670P(Accelerometer+Gyroscope) +======================================================= + +#Preliminary composition 20220716 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +ICM42670_REG_DEVICE_ID = const(0x00) +ICM42670_REG_RESET = const(0x02) +ICM42670_REG_DATA = const(0x09) +ICM42670_REG_PWR_MGMT0 = const(0x1F) +ICM42670_REG_GYRO_CONFIG0 = const(0x20) +ICM42670_REG_ACCEL_CONFIG0 = const(0x21) +ICM42670_REG_APEX_DATA0 = const(0x31) +ICM42670_REG_WHO_AM_I = const(0x75) + +AccRange_16g = 0 +AccRange_8g = 1 +AccRange_4g = 2 +AccRange_2g = 3 + +GyrRange_2000dps = 0 +GyrRange_1000dps = 1 +GyrRange_500dps = 2 +GyrRange_250dps = 3 + +Acc_Gyr_Odr_1600Hz = 0x05 +Acc_Gyr_Odr_800Hz = 0x06 +Acc_Gyr_Odr_400Hz = 0x07 +Acc_Gyr_Odr_200Hz = 0x08 +Acc_Gyr_Odr_100Hz = 0x09 +Acc_Gyr_Odr_50Hz = 0x0A +Acc_Gyr_Odr_25Hz = 0x0B +Acc_Gyr_Odr_12_5Hz = 0x0C + +class ICM42670: + def __init__(self, i2c_bus, addr=0x68, AccRange=AccRange_16g, GyrRange=GyrRange_2000dps, Acc_Gyr_Odr=Acc_Gyr_Odr_100Hz): + self._device = i2c_bus + self._address = addr + if self._chip_id() != 0x67: + raise AttributeError("Cannot find a ICM42670") + + self._wreg(ICM42670_REG_RESET,0x10) #Software reset enabled + time.sleep(0.1) + self._wreg(ICM42670_REG_GYRO_CONFIG0,(GyrRange << 4) | Acc_Gyr_Odr) #Gyr-500HZ/2000dps + self._wreg(ICM42670_REG_ACCEL_CONFIG0,(AccRange << 4) | Acc_Gyr_Odr) #ACC-100HZ/16G + self._wreg(ICM42670_REG_PWR_MGMT0,0x1E) + time.sleep(0.1) + self.acc_lsb_div= 2 ** (11 + AccRange) + self.gyr_lsb_div= 2 ** (14 + GyrRange) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(ICM42670_REG_WHO_AM_I) + + def u2s(self,n): + return n if n < (1 << 15) else n - (1 << 16) + + def getdata(self): + _buffer=self._rreg(ICM42670_REG_DATA,14) + tmp= float(self.u2s(_buffer[0]<<8|_buffer[1]))/128+25 + acc_x=float(self.u2s(_buffer[2]<<8|_buffer[3]))/self.acc_lsb_div + acc_y=float(self.u2s(_buffer[4]<<8|_buffer[5]))/self.acc_lsb_div + acc_z=float(self.u2s(_buffer[6]<<8|_buffer[7]))/self.acc_lsb_div + gyr_x=float(self.u2s(_buffer[8]<<8|_buffer[9]))/self.gyr_lsb_div + gyr_y=float(self.u2s(_buffer[10]<<8|_buffer[11]))/self.gyr_lsb_div + gyr_z=float(self.u2s(_buffer[12]<<8|_buffer[13]))/self.gyr_lsb_div + return (acc_x,acc_y,acc_z),(gyr_x,gyr_y,gyr_z),round(tmp,2) + + def accelerometer(self): + return self.getdata()[0] + + def strength(self): + from math import sqrt + return sqrt(self.accelerometer()[0]**2+self.accelerometer()[1]**2+self.accelerometer()[2]**2) + + def gyroscope(self): + return self.getdata()[1] + + def temperature(self): + return self.getdata()[2] diff --git a/mixly/boards/default/micropython/build/lib/image.py b/mixly/boards/default/micropython/build/lib/image.py new file mode 100644 index 00000000..60c037b3 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/image.py @@ -0,0 +1,87 @@ +""" +Iamge + +MicroPython library for the Iamge(jpeg C module) +======================================================= +@dahanzimin From the Mixly Team +""" +import gc +import urequests +from base64 import b64encode +from jpeg import Encoder, Decoder + +class IMG: + def __init__(self, image, width, height): + self.image = image + self.width = width + self.height = height + self.format = "RGB565" + +class Image: + def save(self, img, path="mixly.jpg", **kwargs): + '''quality(1-100), rotation (0, 90, 180, 270)''' + _encoder = Encoder(pixel_format="RGB565_BE", width=img.width, height=img.height, **kwargs) + _jpeg = _encoder.encode(img.image) + del _encoder + gc.collect() + if isinstance(path, str): + with open(path, 'wb') as f: + f.write(_jpeg) + else: + return _jpeg + + def open(self, path="mixly.jpg", scale_width=None, scale_height=None, tft_width=240, tft_height=240, **kwargs): + '''rotation (0, 90, 180, 270), clipper_width, clipper_height''' + with open(path, "rb") as f: + _jpeg = f.read() + return self._jpg_decoder(_jpeg, scale_width, scale_height, tft_width, tft_height, **kwargs) + + def convert(self, img, formats=0, **kwargs): + if formats == 0: + return self.save(img, None, **kwargs) + elif formats == 1: + return b'data:image/jpg;base64,' + b64encode(self.save(img, None, **kwargs)) + + def download(self, url, path=None, scale_width=None, scale_height=None, tft_width=240, tft_height=240, block=1024, **kwargs): + '''rotation (0, 90, 180, 270), clipper_width, clipper_height''' + response = urequests.get(url, stream=True) + if path is None: + _image = self._jpg_decoder(response.raw.read(), scale_width, scale_height, tft_width, tft_height, **kwargs) + response.close() + return _image + else: + with open(path, 'wb') as f: + while True: + _data = response.raw.read(block) + if not _data: + break + else: + f.write(_data) + response.close() + + def _jpg_decoder(self, jpg, scale_width, scale_height, tft_width, tft_height, **kwargs): + '''Automatically zoom based on the screen''' + if scale_width is None or scale_height is None: + _width = tft_width + _height = tft_height + for i in range(min(len(jpg), 1024)): + if jpg[i] == 0xFF and (jpg[i + 1] & 0xF0) == 0xC0: + if jpg[i + 1] not in [0xC4, 0xC8, 0xCC]: + _width = jpg[i + 7] << 8 | jpg[i + 8] + _height = jpg[i + 5] << 8| jpg[i + 6] + break + if _width > tft_width or _height > tft_height: + _scale = max(_width / tft_width, _height / tft_height) * 8 + _decoder = Decoder(pixel_format="RGB565_BE", scale_width=round(_width / _scale) * 8, scale_height=round(_height / _scale) * 8, **kwargs) + else: + _decoder = Decoder(pixel_format="RGB565_BE", **kwargs) + else: + _decoder = Decoder(pixel_format="RGB565_BE", scale_width=scale_width // 8 * 8, scale_height=scale_height // 8 * 8, **kwargs) + _info = _decoder.get_img_info(jpg) + _image = IMG(_decoder.decode(jpg), _info[0], _info[1]) + del _decoder, jpg + gc.collect() + return _image + +#图像处理 +Image = Image() diff --git a/mixly/boards/default/micropython/build/lib/informatio_picture.py b/mixly/boards/default/micropython/build/lib/informatio_picture.py new file mode 100644 index 00000000..26dc192e --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/informatio_picture.py @@ -0,0 +1,18 @@ +#Take the picture bytes in informatio_picture.py +#--dahanzimin From the Mixly Team + +Accept=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x8c\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x01\xa7\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x03y\x80\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x02~`\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x04\xff0\x00\x7f\x00\x00\x00\x00\x00\x00\x00\t\xff\xec\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x1b\xff\xf6\x00\x7f\x00\x00\x00\x00\x00\x00\x007\xff\xfd\x80\x7f\x00\x00\x00\x00\x00\x00\x00o\xff\xff\x80\x7f\x00\x00\x00\x00\x00\x00\x00_\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x9f\xff\xfe\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xbf\xff\xfc\x00\x7f\x00\x00\x00\x00\x00\x00\x03\x7f\xff\xf8\x00\x7f\x00\x00\x00\x00\x00\x00\x06\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\x00\x05\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x00\x0b\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00\x00\x17\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x007\xff\xfe\x00\x00\x7f\x00\x00\x00\x00\x00\x00o\xff\xfc\x00\x00\x7f\x00\x00\x00\x00\x00\x00_\xff\xf8\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xbf\xff\xf0\x00\x00\x7f\x00\x00\x00\x00\x00\x01\x7f\xff\xe0\x00\x00\x7f\x00\x00\x00\x00\x00\x03\x7f\xff\xc0\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\r\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0b\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00/\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xf0\x00\x00\x00\x7f\x00\x00\x01\xc0\x00\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x1e@\x00\xff\xff\xc0\x00\x00\x00\x7f\x00\x01\xeb \x01\xff\xff\x80\x00\x00\x00\x7f\x00\x1e\xff\xa0\x03\xff\xff\x00\x00\x00\x00\x7f\x00w\xff\xb0\x07\xff\xfe\x00\x00\x00\x00\x7f\x00?\xff\x90\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x1f\xff\xd0\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x1f\xff\xf8\x1f\xff\xf0\x00\x00\x00\x00\x7f\x00\x0f\xff\xe8?\xff\xe0\x00\x00\x00\x00\x7f\x00\x07\xff\xf8\x7f\xff\xc0\x00\x00\x00\x00\x7f\x00\x03\xff\xf4\xff\xff\x80\x00\x00\x00\x00\x7f\x00\x03\xff\xfd\xff\xff\x00\x00\x00\x00\x00\x7f\x00\x01\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x7f\x00\x00\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x7f\x00\x00\x7f\xff\xff\xf8\x00\x00\x00\x00\x00\x7f\x00\x00\x7f\xff\xff\xf0\x00\x00\x00\x00\x00\x7f\x00\x00?\xff\xff\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x1f\xff\xff\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x0f\xff\xff\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\xff\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x03\xff\xf8\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x01\xff\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xff\xe0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Backward=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0b\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xf7\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xfdW\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xf2\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xe4\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xe8\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xd8\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xa0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff@\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xfd\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Decline=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\x05\x00\x00\x00\x7f\x00\x00\x00\xfc\x00\x00\x00\x0f\x80\x00\x00\x7f\x00\x00\x01\xfe\x00\x00\x00\x17\xc0\x00\x00\x7f\x00\x00\x03\xff\x00\x00\x00?\xa0\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00_\xf0\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x00\xff\xe8\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x01\x7f\xfc\x00\x00\x7f\x00\x00?\xff\xf0\x00\x03\xff\xfa\x00\x00\x7f\x00\x00\x7f\xff\xf8\x00\x05\xff\xff\x00\x00\x7f\x00\x00\xff\xff\xfc\x00\x0f\xff\xfe\x80\x00\x7f\x00\x01\xff\xff\xfe\x00\x17\xff\xff\xc0\x00\x7f\x00\x01\xff\xff\xff\x00?\xff\xff\xc0\x00\x7f\x00\x00\xff\xff\xff\x80_\xff\xff\x80\x00\x7f\x00\x00\x7f\xff\xff\xc0\xff\xff\xff\x00\x00\x7f\x00\x00?\xff\xff\xe1\x7f\xff\xfe\x00\x00\x7f\x00\x00\x1f\xff\xff\xf3\xff\xff\xfc\x00\x00\x7f\x00\x00\x0f\xff\xff\xfd\xff\xff\xf8\x00\x00\x7f\x00\x00\x07\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x03\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x00\xff\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x0b\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00/\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\xbf\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\x02\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x07\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0b\xff\xff\xf7\xff\xff\xfc\x00\x00\x7f\x00\x00\x1f\xff\xff\xe3\xff\xff\xfe\x00\x00\x7f\x00\x00/\xff\xff\xc1\xff\xff\xff\x00\x00\x7f\x00\x00\x7f\xff\xff\x80\xff\xff\xff\x80\x00\x7f\x00\x00\xbf\xff\xff\x00\x7f\xff\xff\xc0\x00\x7f\x00\x01\xff\xff\xfe\x00?\xff\xff\xc0\x00\x7f\x00\x00\xff\xff\xfc\x00\x1f\xff\xff\xc0\x00\x7f\x00\x00\x7f\xff\xf8\x00\x0f\xff\xff\x80\x00\x7f\x00\x00?\xff\xf0\x00\x07\xff\xff\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x03\xff\xfe\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x01\xff\xfc\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00\xff\xf8\x00\x00\x7f\x00\x00\x03\xff\x00\x00\x00\x7f\xf0\x00\x00\x7f\x00\x00\x01\xfe\x00\x00\x00?\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00\x00\x00\x1f\xc0\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\x0f\x80\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x07\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Forward=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00+\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00]\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xdc\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xbe\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x7f`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x02\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x90\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05\xff\xd8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xec\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x17\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xf2\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfb\x00\x00\x00\x00\x7f\x00\x00\x00\x00_\xff\xfd\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xfe@\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff`\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xd0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xc8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xec\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xf4\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf2\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01>\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x06~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\r\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x13\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00g\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xdf\xff\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x01?\xffUUUUX\x00\x7f\x00\x00\x06\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xff\xe8\x00\x7f\x00\x00\x17\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x01\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x01\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x1f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x03\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x00\xff\xff\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00?\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1f\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +No_go=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xfc>\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xc3\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xf8`\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\x18\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xcc\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf3\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xc1\xff\xfd\x80\x00\x00\x7f\x00\x00\x00\xff\xfc\x00\x1f\xfc\xc0\x00\x00\x7f\x00\x00\x01\xff\xf0\x00\x03\xff`\x00\x00\x7f\x00\x00\x03\xff\xc0\x00\x00\xf7\xb0\x00\x00\x7f\x00\x00\x07\xff\x00\x00\x00\x7f\xd0\x00\x00\x7f\x00\x00\x0f\xfe\x00\x00\x00_\xe8\x00\x00\x7f\x00\x00\x0f\xf8\x00\x00\x00\xff\xf4\x00\x00\x7f\x00\x00\x1f\xf0\x00\x00\x01\x7f\xf4\x00\x00\x7f\x00\x00?\xf0\x00\x00\x03\xff\xfa\x00\x00\x7f\x00\x00?\xe0\x00\x00\x05\xff\xfb\x00\x00\x7f\x00\x00\x7f\xc0\x00\x00\x0f\xfd\xfd\x00\x00\x7f\x00\x00\x7f\xc0\x00\x00\x17\xf8\xfd\x00\x00\x7f\x00\x00\x7f\x80\x00\x00?\xf0\xff\x80\x00\x7f\x00\x00\xff\x80\x00\x00_\xe0~\x80\x00\x7f\x00\x00\xff\x00\x00\x00\xff\xc0\x7f\x80\x00\x7f\x00\x00\xff\x00\x00\x01\x7f\x80?@\x00\x7f\x00\x00\xfe\x00\x00\x03\xff\x00?@\x00\x7f\x00\x01\xfe\x00\x00\x05\xfe\x00?@\x00\x7f\x00\x01\xfe\x00\x00\x0f\xfc\x00\x1f\xc0\x00\x7f\x00\x01\xfe\x00\x00\x17\xf8\x00\x1f\xc0\x00\x7f\x00\x01\xfc\x00\x00?\xf0\x00\x1f\xe0\x00\x7f\x00\x01\xfc\x00\x00_\xe0\x00\x1f\xa0\x00\x7f\x00\x01\xfc\x00\x00\xff\xc0\x00\x1f\xe0\x00\x7f\x00\x01\xfc\x00\x01\x7f\x80\x00\x1f\xa0\x00\x7f\x00\x01\xfc\x00\x03\xff\x00\x00\x1f\xe0\x00\x7f\x00\x01\xfe\x00\x05\xfe\x00\x00\x1f\xe0\x00\x7f\x00\x01\xfe\x00\x0f\xfc\x00\x00\x1f\xc0\x00\x7f\x00\x01\xfe\x00\x17\xf8\x00\x00?\xc0\x00\x7f\x00\x01\xfe\x00?\xf0\x00\x00?\xc0\x00\x7f\x00\x00\xff\x00_\xe0\x00\x00?\xc0\x00\x7f\x00\x00\xff\x00\xff\xc0\x00\x00\x7f\xc0\x00\x7f\x00\x00\xff\x01\xff\x80\x00\x00\x7f\x80\x00\x7f\x00\x00\xff\x83\xff\x00\x00\x00\x7f\x80\x00\x7f\x00\x00\x7f\x87\xfe\x00\x00\x00\xff\x80\x00\x7f\x00\x00\x7f\xcf\xfc\x00\x00\x01\xff\x00\x00\x7f\x00\x00?\xff\xf8\x00\x00\x01\xff\x00\x00\x7f\x00\x00?\xff\xf0\x00\x00\x03\xfe\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x00\x07\xfe\x00\x00\x7f\x00\x00\x1f\xff\xc0\x00\x00\x07\xfc\x00\x00\x7f\x00\x00\x0f\xff\x80\x00\x00\x1f\xfc\x00\x00\x7f\x00\x00\x07\xff\x00\x00\x00?\xf8\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00\xff\xf0\x00\x00\x7f\x00\x00\x03\xff\xe0\x00\x01\xff\xe0\x00\x00\x7f\x00\x00\x01\xff\xf8\x00\x0f\xff\xc0\x00\x00\x7f\x00\x00\x00\xff\xff\x00\x7f\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Question_mark=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\x1e\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xe3\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfc\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xc8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xe4\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xf1\xff\xf2\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\x80\x7f\xf9\x00\x00\x00\x7f\x00\x00\x00?\xfe\x00\x1f\xfd\x00\x00\x00\x7f\x00\x00\x00?\xfc\x00\x07\xfd\x80\x00\x00\x7f\x00\x00\x00?\xf8\x00\x07\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf8\x00\x03\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x03\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x01\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xe0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xe0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x03\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x07\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x01\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xfd\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xfe\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff@\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00&\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00,\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?`\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00/\xb0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xcc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00/\xf6\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfb\x00\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xef\xfc\xc0\x00\x00\x7f\x00\x05UUUU_\xff`\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xb0\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xcc\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf6\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfb\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfc\xc0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff`\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xb0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xb0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfe`\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfc\x80\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfb\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf6\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xb0\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff`\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xf0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Stop_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xfc\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x07\x80\x00\x00\xd0\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00h\x00\x00\x00\x7f\x00\x00\x00\x1e\x7f\xff\xff4\x00\x00\x00\x7f\x00\x00\x00<\xff\xff\xff\x9a\x00\x00\x00\x7f\x00\x00\x00y\xff\xff\xff\xcd\x00\x00\x00\x7f\x00\x00\x00\xf3\xff\xff\xff\xe6\x80\x00\x00\x7f\x00\x00\x01\xe7\xff\xff\xff\xf3@\x00\x00\x7f\x00\x00\x03\xcf\xff\xff\xff\xf9\xa0\x00\x00\x7f\x00\x00\x07\x9f\xff\xff\xff\xfc\xd0\x00\x00\x7f\x00\x00\x0f?\xff\xff\xff\xfeh\x00\x00\x7f\x00\x00\x1e\x7f\xff\xff\xff\xff4\x00\x00\x7f\x00\x00<\xff\xff\xff\xff\xff\x9a\x00\x00\x7f\x00\x00y\xff\xff\xff\xff\xff\xcd\x00\x00\x7f\x00\x00\xf3\xff\xff\xff\xff\xff\xe6\x80\x00\x7f\x00\x01\xe7\xff\xff\xff\xff\xff\xf3@\x00\x7f\x00\x03\xcf\xff\xff\xff\xff\xff\xf9\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\x9e\x0f\x00<\x0f\xc0<\xa0\x00\x7f\x00\x03\x9c\x02\x00\x18\x07\x80\x0c\xa0\x00\x7f\x00\x03\x98\x02\x00\x10\x03\x80\x04\xa0\x00\x7f\x00\x03\x90\xe1\xe0\xf1\xe3\x8f\xc4\xa0\x00\x7f\x00\x03\x91\xf7\xf1\xe3\xf1\x8f\xe4\xa0\x00\x7f\x00\x03\x91\xff\xf1\xe3\xf1\x8f\xe0\xa0\x00\x7f\x00\x03\x98\xff\xf1\xc7\xf9\x8f\xe4\xa0\x00\x7f\x00\x03\x98?\xf1\xc7\xf8\x8f\xc4\xa0\x00\x7f\x00\x03\x9c\x0f\xf1\xc7\xf8\x87\x84\xa0\x00\x7f\x00\x03\x9e\x03\xf1\xc7\xf8\x80\x0c\xa0\x00\x7f\x00\x03\x9f\x81\xf1\xc7\xf8\x80\x1c\xa0\x00\x7f\x00\x03\x9f\xe1\xf1\xc7\xf8\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf1\xf1\xc7\xf8\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf8\xf1\xe3\xf1\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf8\xf1\xe3\xf1\x87\xfc\xa0\x00\x7f\x00\x03\x91\xf1\xf1\xe1\xe1\x87\xfc\xa0\x00\x7f\x00\x03\x90\x01\xf1\xf0\xc3\x87\xfc\xa0\x00\x7f\x00\x03\x98\x01\xf1\xf8\x07\x87\xfc\xa0\x00\x7f\x00\x03\x9c\x07\xf1\xfc\x0f\x87\xfc\xa0\x00\x7f\x00\x03\x9f\x1f\xff\xff?\xff\xfc\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\xcf\xff\xff\xff\xff\xff\xf9\xa0\x00\x7f\x00\x01\xe7\xff\xff\xff\xff\xff\xf3@\x00\x7f\x00\x00\xf3\xff\xff\xff\xff\xff\xe6\x80\x00\x7f\x00\x00y\xff\xff\xff\xff\xff\xcd\x00\x00\x7f\x00\x00<\xff\xff\xff\xff\xff\x9a\x00\x00\x7f\x00\x00\x1e\x7f\xff\xff\xff\xff4\x00\x00\x7f\x00\x00\x0f?\xff\xff\xff\xfeh\x00\x00\x7f\x00\x00\x07\x9f\xff\xff\xff\xfc\xf0\x00\x00\x7f\x00\x00\x03\xcf\xff\xff\xff\xf9\xe0\x00\x00\x7f\x00\x00\x01\xe7\xff\xff\xff\xf3\xc0\x00\x00\x7f\x00\x00\x00\xf3\xff\xff\xff\xe7\x80\x00\x00\x7f\x00\x00\x00y\xff\xff\xff\xcf\x00\x00\x00\x7f\x00\x00\x00<\xff\xff\xff\x9e\x00\x00\x00\x7f\x00\x00\x00\x1e\x7f\xff\xff<\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00x\x00\x00\x00\x7f\x00\x00\x00\x07\x80\x00\x00\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Stop_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xfc\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x07\xc0\x00\x00\xd0\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00h\x00\x00\x00\x7f\x00\x00\x00\x1e\x00\x00\x004\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1a\x00\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\r\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x06\x80\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x03@\x00\x00\x7f\x00\x00\x03\xc0\x00\x00\x00\x01\xa0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00\xd0\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x00h\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x004\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x1a\x00\x00\x7f\x00\x00x\x00\x00\x00\x00\x00\r\x00\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x06\x80\x00\x7f\x00\x01\xe0\x00\x00\x00\x00\x00\x03@\x00\x7f\x00\x03\xc0\x00\x00\x00\x00\x00\x01\xa0\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00\xa0\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00\xa0\x00\x7f\x00\x03\x81\xf0\xff\xc3\xf0?\xc0\xa0\x00\x7f\x00\x03\x83\xfd\xff\xe7\xf8\x7f\xf0\xa0\x00\x7f\x00\x03\x87\xff\xff\xef\xfc\x7f\xf8\xa0\x00\x7f\x00\x03\x8f\x1e\x1f\x0e\x1cp8\xa0\x00\x7f\x00\x03\x8e\x08\x0e\x1c\x0ep\x1c\xa0\x00\x7f\x00\x03\x8e\x00\x0e\x1c\x0ep\x1c\xa0\x00\x7f\x00\x03\x87\x00\x0e8\x06p\x1c\xa0\x00\x7f\x00\x03\x87\xc0\x0e8\x07p8\xa0\x00\x7f\x00\x03\x83\xf0\x0e8\x07xx\xa0\x00\x7f\x00\x03\x81\xfc\x0e8\x07\x7f\xf0\xa0\x00\x7f\x00\x03\x80~\x0e8\x07\x7f\xe0\xa0\x00\x7f\x00\x03\x80\x1e\x0e8\x07x\x00\xa0\x00\x7f\x00\x03\x80\x0e\x0e8\x07x\x00\xa0\x00\x7f\x00\x03\x80\x07\x0e\x1c\x0ex\x00\xa0\x00\x7f\x00\x03\x80\x07\x0e\x1c\x0ex\x00\xa0\x00\x7f\x00\x03\x8e\x0e\x0e\x1e\x1ex\x00\xa0\x00\x7f\x00\x03\x8f\xfe\x0e\x0f\x00\x00\x00\x00\x7f\x00\x00\x00\x00>>\x1d\x00\x00\x00\x00\x7f\x00\x00\x00\x00<{\x0f\x00\x00\x00\x00\x7f\x00\x00\x00\x00|y\x0e\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\xfe\x87\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\xfe\x87\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\xff\x83\xa0\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\xfe\x83\xe0\x00\x00\x00\x7f\x00\x00\x00\x03\xe0\xff\x81\xd0\x00\x00\x00\x7f\x00\x00\x00\x03\xc0\xff\x80\xf0\x00\x00\x00\x7f\x00\x00\x00\x07\xc0\x7f\x00\xe8\x00\x00\x00\x7f\x00\x00\x00\x0f\x80\x7f\x00|\x00\x00\x00\x7f\x00\x00\x00\x0f\x80\x7f\x00t\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x7f\x00>\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x7f\x00>\x00\x00\x00\x7f\x00\x00\x00>\x00\x7f\x00\x1d\x00\x00\x00\x7f\x00\x00\x00>\x00\x7f\x00\x1f\x00\x00\x00\x7f\x00\x00\x00|\x00\x7f\x00\x0e\x80\x00\x00\x7f\x00\x00\x00\xf8\x00\x7f\x00\x07\xc0\x00\x00\x7f\x00\x00\x00\xf8\x00\x7f\x00\x07@\x00\x00\x7f\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x7f\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x7f\x00\x00\x03\xe0\x00>\x00\x01\xd0\x00\x00\x7f\x00\x00\x03\xe0\x00>\x00\x01\xf0\x00\x00\x7f\x00\x00\x07\xc0\x00>\x00\x00\xe8\x00\x00\x7f\x00\x00\x0f\xc0\x00>\x00\x00\xfc\x00\x00\x7f\x00\x00\x0f\x80\x00\x1c\x00\x00t\x00\x00\x7f\x00\x00\x1f\x00\x00\x00\x00\x00>\x00\x00\x7f\x00\x00\x1f\x00\x00\x00\x00\x00:\x00\x00\x7f\x00\x00>\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00>\x00\x00>\x00\x00\x1f\x00\x00\x7f\x00\x00|\x00\x00}\x00\x00\x0e\x80\x00\x7f\x00\x00\xfc\x00\x00~\x80\x00\x0f\xc0\x00\x7f\x00\x00\xf8\x00\x00\x7f\x80\x00\x07@\x00\x7f\x00\x01\xf8\x00\x00\x7f\x80\x00\x07\xe0\x00\x7f\x00\x01\xf0\x00\x00\x7f\x00\x00\x03\xa0\x00\x7f\x00\x03\xe0\x00\x00?\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x1e\x00\x00\x01\xf0\x00\x7f\x00\x07\xc0\x00\x00\x00\x00\x00\x00\xe8\x00\x7f\x00\x0f\xc0\x00\x00\x00\x00\x00\x00\xfc\x00\x7f\x00\x0f\x80\x00\x00\x00\x00\x00\x00\xf4\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +YES=Accept +NO=Decline diff --git a/mixly/boards/default/micropython/build/lib/irremote.py b/mixly/boards/default/micropython/build/lib/irremote.py new file mode 100644 index 00000000..756844ea --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/irremote.py @@ -0,0 +1,259 @@ +""" +IR-Remote + +Micropython library for the IR-Remote/Timer(IR_RX&TX) +=============================================== +@dahanzimin From the Mixly Team +""" +import array, time, gc +from machine import Pin, Timer +from os import uname +try: + from esp32 import RMT + TX_MOED = 1 +except: + from machine import PWM + TX_MOED = 0 + +'''接收部分''' +class IR_RX: + BADSTART = 'Invalid start pulse' + BADDATA = 'Invalid data' + def __init__(self, pin, callback=None, timeout=15000, timer_id=1): + self._start = 0 + self._ready = False + self._enable = False + self._timeout = timeout + self._callback = callback + self._pulses = array.array('H') + self.code = [None, None, None, memoryview(self._pulses)] #存放[cmd, addr, data, pulses] + Pin(pin, Pin.IN).irq(handler=self._irq_cb, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING)) + Timer(0 if "-C2" in uname().machine else timer_id).init(period=5, mode=Timer.PERIODIC, callback=self._timer_cb) + + def _irq_cb(self, pin): + if not self._enable: + _intime = time.ticks_us() + if self._start == 0: + self._start = _intime + return + self._pulses.append(time.ticks_diff(_intime, self._start)) + self._start = _intime + else: + self._start = 0 + self._pulses = array.array('H') + + def _timer_cb(self, tim): + if len(self._pulses) >= 3 and time.ticks_diff(time.ticks_us(), self._start) > self._timeout: + #接收完成,开始解码 + self.code[3] = memoryview(self._pulses) + if self.decode() is None and self._callback: + self._callback(self.code[0], self.code[1], self.code[2], self.code[3]) + self._ready = True + self._start = 0 + self._pulses = array.array('H') + gc.collect() + + def recv_cb(self, callback): + self._callback = callback + + def timeout(self, timeout=15000): + self._timeout = timeout + + def any(self): + ready = self._ready + self._ready = False + return ready + + def enable(self, onoff): + self._enable = onoff + +class NEC_RX(IR_RX): + def __init__(self, pin, bits=None, callback=None, timer_id=1): + super().__init__(pin, callback, timer_id=timer_id) + self._bits = bits + + def decode(self): + pulse_len = len(self._pulses) + if pulse_len < 3: + print("Warning:", self.BADSTART) + return False + else: + start_i = 0 + value = 0 + #跳过帧头(各厂家定义不一) + for i in range(pulse_len): + if self._pulses[i] <= 2250: + start_i = i + break + val = 1 << ((pulse_len - start_i - 1) // 2) - 1 if (pulse_len - start_i) >= 3 else 0 + #根据高低脉冲定义转码 + for edge in range(start_i, pulse_len - 1, 2): + value >>= 1 + if self._pulses[edge + 1] > 1120: + value |= val + #判读是8、16位解码 + if self._bits == 8 or self._bits == 16: + cmd = value >> 16 & 0xff + if cmd != (value >> 24 ^ 0xff) and value != 0x0: + print("Warning:", self.BADDATA) + return False + addr = value & 0xff if self._bits == 8 else value & 0xffff + self.code[0:3] = cmd, addr, value + #其他未定义直接输出转码 + else: + self.code[0:3] = None, None, value + +class RC5_RX(IR_RX): + def __init__(self, pin, callback=None, timer_id=1): + super().__init__(pin, callback, timer_id=timer_id) + + def decode(self): + pulse_len = len(self._pulses) + if pulse_len < 3: + print("Warning:", self.BADSTART) + return False + else: + bit = 1 + value = 0 + num = 0 + while True: + short = self._pulses[num] < 1334 + if not short: + bit ^= 1 + value <<= 1 + value |= bit + num += 1 + int(short) + if num >= pulse_len: + value >>= 1 + break + #判读解码 + cmd = (value & 0x3f) | (0 if ((value >> 12) & 1) else 0x40) + addr = (value >> 6) & 0x1f + self.code[0:3] = cmd, addr, value + +'''发射部分''' +class IR_TX: + def __init__(self, pin, cfreq=38000, power=60): + if TX_MOED: + self._rmt = RMT(0, pin=Pin(pin), clock_div=80, tx_carrier = (cfreq, round(power * 0.75), 1)) + else: + self._pwm = PWM(Pin(pin), freq=cfreq, duty_u16=0) + self._duty = round(power * 65535 / 100 * 0.75) + self._busy = False + self._pulses = array.array('H') + self.carrier = False + + def _pwm_write_pulses(self, pulses): + _flip = True + self._busy = True + for pulse in pulses: + if _flip: + self._pwm.duty_u16(self._duty) + time.sleep_us(pulse) + _flip = False + else: + self._pwm.duty_u16(0) + time.sleep_us(pulse) + _flip = True + self._pwm.duty_u16(0) + self._busy = False + + def transmit(self, cmd=None, addr=None, toggle=None, pulses=None, raw=None): + if pulses is None: + self.carrier = False + if raw is None: + self.tx(cmd, addr, toggle) + else: + self.tx_raw(raw) + if TX_MOED: + self._rmt.write_pulses(tuple(self._pulses)) + else: + self._pwm_write_pulses(tuple(self._pulses)) + self._pulses = array.array('H') + else: + if TX_MOED: + self._rmt.write_pulses(tuple(pulses)) + else: + self._pwm_write_pulses(tuple(pulses)) + + def busy(self): + return not self._rmt.wait_done() if TX_MOED else self._busy + + def _append(self, *times): + for t in times: + self._pulses.append(t) + self.carrier = not self.carrier + + def _add(self, t): + assert t > 0 + self._pulses[len(self._pulses)-1] +=t + +class NEC_TX(IR_TX): + _TBURST = const(563) + _T_ONE = const(1687) + def __init__(self, pin, samsung=False, power=60): + super().__init__(pin, 38000, power) + self._samsung = samsung + + def _bit(self, b): + self._append(_TBURST, _T_ONE if b else _TBURST) + + def tx(self, cmd, addr, toggle=0): #cmd:0~0xff, addr:0~0xffff, toggle:0,1 + if self._samsung: + self._append(4500, 4500) + else: + self._append(9000, 4500) + if addr < 256: # Short address: append complement + if self._samsung: + addr |= addr << 8 + else: + addr |= ((addr ^ 0xff) << 8) + for _ in range(16): + self._bit(addr & 1) + addr >>= 1 + cmd |= ((cmd ^ 0xff) << 8) + for _ in range(16): + self._bit(cmd & 1) + cmd >>= 1 + self._append(_TBURST) + if toggle == 1: + self._append(30000, 9000, 2250, _TBURST) + + def tx_raw(self, raw): + self._append(9000, 4500) + while raw: + self._bit(raw & 1) + raw >>= 1 + self._append(_TBURST) + +class RC5_TX(IR_TX): + _T_RC5 = const(889) + def __init__(self, pin, power=60): + super().__init__(pin, 36000, power) + + def tx(self, cmd, addr, toggle): #cmd:0~0x3f, addr:0~0x1f, toggle:0,1 + d = (cmd & 0x3f) | ((addr & 0x1f) << 6) | (((cmd & 0x40) ^ 0x40) << 6) | ((toggle & 1) << 11) + mask = 0x2000 + while mask: + if mask == 0x2000: + self._append(_T_RC5) + else: + bit = bool(d & mask) + if bit ^ self.carrier: + self._add(_T_RC5) + self._append(_T_RC5) + else: + self._append(_T_RC5, _T_RC5) + mask >>= 1 + + def tx_raw(self, raw): + self._append(_T_RC5) + mask = 1 << len(bin(raw)) - 3 + while mask: + if bool(raw & mask) ^ self.carrier: + self._add(_T_RC5) + self._append(_T_RC5) + else: + self._append(_T_RC5, _T_RC5) + mask >>= 1 + self._append(_T_RC5) diff --git a/mixly/boards/default/micropython/build/lib/keypad.py b/mixly/boards/default/micropython/build/lib/keypad.py new file mode 100644 index 00000000..f23e9cbe --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/keypad.py @@ -0,0 +1,49 @@ +""" +Simple Keypad + +Micropython library for the Simple Keypad +======================================================= + +#Based on Author: 'Teeraphat Kullanankanjana' +@dahanzimin From the Mixly Team +""" + +from machine import Pin +from time import sleep + +class Keypad: + def __init__(self, row_pins, column_pins, keys): + """Initialize the keypad object.""" + if not all(isinstance(pin, Pin) for pin in row_pins): + raise ValueError("Row pins must be instances of Pin.") + + if not all(isinstance(pin, Pin) for pin in column_pins): + raise ValueError("Column pins must be instances of Pin.") + + if not isinstance(keys, list) or not all(isinstance(row, list) for row in keys): + raise ValueError("Keys must be a 2D list.") + + self.row_pins = row_pins + self.column_pins = column_pins + self.keys = keys + + for pin in self.row_pins: + pin.init(Pin.IN, Pin.PULL_UP) + + for pin in self.column_pins: + pin.init(Pin.OUT) + + if len(self.row_pins) > len(self.keys) or len(self.column_pins) > len(self.keys[0]): + raise ValueError("Number of row/column pins does not match the key layout size.") + + def read_keypad(self): + """Read the keypad and return the pressed key.""" + for col_pin in self.column_pins: + col_pin.value(0) + for i, row_pin in enumerate(self.row_pins): + if not row_pin.value(): + key_pressed = self.keys[i][self.column_pins.index(col_pin)] + col_pin.value(1) + return key_pressed + col_pin.value(1) + return None diff --git a/mixly/boards/default/micropython/build/lib/ltr308al.py b/mixly/boards/default/micropython/build/lib/ltr308al.py new file mode 100644 index 00000000..2f2fc5fc --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ltr308al.py @@ -0,0 +1,76 @@ +""" +LTR-308ALS + +Micropython library for the LTR-308ALS +======================================================= + +#Changed from circuitpython to micropython 20220211 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +LTR_308ALS_ADDRESS = const(0x53) + +LTR_308ALS_REG_CTRL = const(0x00) +LTR_308ALS_REG_GAIN = const(0x05) #设置增益 +LTR_308ALS_REG_DEVICE_ID = const(0x06) +LTR_308ALS_REG_DATA = const(0x0D) + +#设置增益范围 +LTR_308ALS_CMD_ALS_Enable = const(0x02) +LTR_308ALS_CMD_X1GAIN =const(0x00) +LTR_308ALS_CMD_X3GAIN =const(0x01) +LTR_308ALS_CMD_X6GAIN =const(0x02) +LTR_308ALS_CMD_X9GAIN =const(0x03) +LTR_308ALS_CMD_X18GAIN =const(0x04) + +_GAINS = ( + LTR_308ALS_CMD_X1GAIN, # 1x + LTR_308ALS_CMD_X3GAIN, # 3x + LTR_308ALS_CMD_X6GAIN, # 6x + LTR_308ALS_CMD_X9GAIN, # 9x + LTR_308ALS_CMD_X18GAIN # 18x +) + +_GAINS_X = ( + 1, # 1x + 3, # 3x + 6, # 6x + 9, # 9x + 18 # 18x +) + +class LTR_308ALS: + def __init__(self, i2c_bus,gain=1): + self._device = i2c_bus + self._address = LTR_308ALS_ADDRESS + self._gain = gain + + if self._chip_id() != 0xB1: + raise AttributeError("Cannot find a LTR_308ALS") + self._Enable() #star + time.sleep(0.2) + self._wreg(LTR_308ALS_REG_GAIN,_GAINS[self._gain]) + + #Write memory address + def _wreg(self, reg, val): + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + #Read memory address + def _rreg(self, reg,nbytes=1): + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(LTR_308ALS_REG_DEVICE_ID) + + def _Enable(self): + self._wreg(LTR_308ALS_REG_CTRL,LTR_308ALS_CMD_ALS_Enable) + + def getdata(self): + buffer=self._rreg(LTR_308ALS_REG_DATA,3) + als_data= buffer[2]<<16 | buffer[1]<<8| buffer[0] + als_lux=float(0.6*als_data/_GAINS_X[self._gain]) + return als_lux + diff --git a/mixly/boards/default/micropython/build/lib/ltr381rgb.py b/mixly/boards/default/micropython/build/lib/ltr381rgb.py new file mode 100644 index 00000000..c285235d --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ltr381rgb.py @@ -0,0 +1,78 @@ +""" +LTR-381RGB-XX + +MicroPython library for the LTR-381RGB-XX (Color sensor) +======================================================= + +#Preliminary composition 20230417 + +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +LTR_MAIN_CTRL = const(0x00) +LTR_ALS_CS_MEAS_RATE = const(0x04) +LTR_ALS_CS_GAIN = const(0x05) +LTR_PART_ID = const(0x06) +LTR_MAIN_STATUS = const(0x07) +LTR_CS_DATA = const(0x0A) + #1x 3x 6x 9x 18x +_GAINS_X = (1, 3, 6, 9, 18) + +class LTR_381RGB: + def __init__(self, i2c_bus, addr=0x53, gain=1): + self._device = i2c_bus + self._address = addr + self._gain = gain + self._color = [0, 0, 0] + self._ir = 0 + self._als = 0 + + if (self._chip_id() & 0xF0) != 0xC0: + raise AttributeError("Cannot find a LTR-381RGB") + + self._configure() + time.sleep(0.1) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + '''Proofreading device ID''' + return self._rreg(LTR_PART_ID) + + def _configure(self): + '''Configuration Register''' + self._wreg(LTR_MAIN_CTRL, 0x06) #CS mode & ALS/CS Enable + self._wreg(LTR_ALS_CS_MEAS_RATE, 0x22) #Resolution = 18 bit, Meas Rate =100ms + self._wreg(LTR_ALS_CS_GAIN, self._gain & 0x07) #CS measurement Gain Range + + def status(self): + '''Data conversion status''' + return self._rreg(LTR_MAIN_STATUS) & 0x08 + + def getdata(self): + '''Processing data acquisition''' + if self.status(): + _buf=self._rreg(LTR_CS_DATA, 12) + self._ir = _buf[2] << 16 | _buf[1] << 8 | _buf[0] + self._color [1] = _buf[5] << 16 | _buf[4] << 8 | _buf[3] + self._color [0] = _buf[8] << 16 | _buf[7] << 8 | _buf[6] + self._color [2] = _buf[11] << 16 | _buf[10] << 8 | _buf[9] + self._als = 0.8 * self._color [1] * (1 - 0.033 * self._ir / self._color [1]) / _GAINS_X[self._gain] + return round(self._als, 2), self._ir, self._color + + def color(self): + return self.getdata()[2] + + def ir(self): + return self.getdata()[1] + + def als(self): + return self.getdata()[0] diff --git a/mixly/boards/default/micropython/build/lib/ltr390uv.py b/mixly/boards/default/micropython/build/lib/ltr390uv.py new file mode 100644 index 00000000..a4ec5727 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ltr390uv.py @@ -0,0 +1,75 @@ +""" +LTR-390UV + +Micropython library for the LTR-390UV(ALS+UV) +======================================================= + +#Preliminary composition 20240120 + +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_LTR390_ADDRESS = const(0x53) +_LTR390_REG_CTRL = const(0x00) +_LTR390_REG_MEAS = const(0x04) +_LTR390_REG_GAIN = const(0x05) +_LTR390_REG_ID = const(0x06) +_LTR390_REG_ALS = const(0x0D) +_LTR390_REG_UVS = const(0x10) + +_RATE_DEFAULT = const(0x02) #100ms +_RESOLUTION_20BIT = (0<<4, 4) +_RESOLUTION_19BIT = (1<<4, 2) +_RESOLUTION_18BIT = (2<<4, 1) +_RESOLUTION_17BIT = (3<<4, 0.5) +_RESOLUTION_16BIT = (4<<4, 0.25) +_RESOLUTION_13BIT = (5<<4, 0.125) + +_GAIN_X1 = (0, 1) +_GAIN_X3 = (1, 3) +_GAIN_X6 = (2, 6) +_GAIN_X9 = (3, 9) +_GAIN_X18 = (4, 18) + +class ALS_UVS: + def __init__(self, i2c_bus, addr=_LTR390_ADDRESS, gain=_GAIN_X1, resolution=_RESOLUTION_17BIT): + self._device = i2c_bus + self._address = addr + self._gain = gain + self._reso = resolution + self._flaga = False + self._flagu = False + + if self._rreg(_LTR390_REG_ID) != 0xB2: + raise AttributeError("Cannot find a LTR-390UV") + + self._wreg(_LTR390_REG_MEAS, self._reso[0] | _RATE_DEFAULT) + self._wreg(_LTR390_REG_GAIN, self._gain[0]) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def ultraviolet(self): + if not self._flagu: + self._wreg(_LTR390_REG_CTRL, 0x0A) #UVS in Active Mode + time.sleep_ms(int(self._reso[1] * 100)) + self._flagu = True + self._flaga = False + buf = self._rreg(_LTR390_REG_UVS, 3) + return buf[2] << 16 | buf[1] << 8 | buf[0] + + def ambient_light(self): + if not self._flaga: + self._wreg(_LTR390_REG_CTRL, 0x02) #ALS in Active Mode + time.sleep_ms(int(self._reso[1] * 100)) + self._flaga = True + self._flagu = False + buf = self._rreg(_LTR390_REG_ALS, 3) + return 0.6 * (buf[2] << 16 | buf[1] << 8 | buf[0]) / (self._gain[1] * self._reso[1]) diff --git a/mixly/boards/default/micropython/build/lib/ltr553als.py b/mixly/boards/default/micropython/build/lib/ltr553als.py new file mode 100644 index 00000000..e3397b3c --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ltr553als.py @@ -0,0 +1,106 @@ +""" +LTR-553ALS-XX + +MicroPython library for the LTR-553ALS-XX(ALS,PS) +======================================================= + +#Preliminary composition 20220224 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +LTR_553ALS_ADDRESS = const(0x23) +LTR_ALS_REG_CONTR = const(0x80) +LTR_PS_REG_CONTR = const(0x81) +LTR_PS_REG_LED = const(0x82) +LTR_PS_REG_PULSES = const(0x83) +LTR_PS_REG_RATE = const(0x84) +LTR_ALS_REG_RATE = const(0x85) +LTR_553ALS_REG_ID = const(0x87) +LTR_ALS_REG_DATA1 = const(0x88) +LTR_553ALS_REG_ATATUS = const(0x8C) +LTR_PS_REG_DATA1 = const(0x8D) + +_ALS_GAIN={ + "X1":(1,0x01), # For Gain X1 + "X2":(2,0x05), # For Gain X2 + "X4":(4,0x09), # For Gain X4 + "X8":(8,0x0D), # For Gain X8 + "X48":(48,0x19), # For Gain X48 + "X96":(96,0x1D), # For Gain X96 +} + +class LTR_553ALS: + + def __init__(self, i2c_bus,addr=LTR_553ALS_ADDRESS,ALS_Gain="X1"): + self._device = i2c_bus + self._address = addr + self.ALS_IR = 0 + self.ALS_VIS = 0 + self.PS = 0 + self.ALS_gain = ALS_Gain + + if self._chip_id() != 0x05: + raise AttributeError("Cannot find a LTR_553ALS") + + self._configure() + #time.sleep(0.1) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + '''校对设备ID''' + return self._rreg(LTR_553ALS_REG_ID) + + def _configure(self): + '''配置寄存器''' + self._wreg(LTR_ALS_REG_CONTR,_ALS_GAIN[self.ALS_gain][1]) # ALS_CONTR: Active mode + self._wreg(LTR_PS_REG_CONTR,0x03) # PS_CONTR: Active mode + self._wreg(LTR_PS_REG_LED,0x5B) #PS_LED: LED_pulse_period=50khz,DUTY = 100%,LED_pulsed_current_level = 50mA + self._wreg(LTR_PS_REG_PULSES,0x0A) #PS_N_Pulses: Number_of_pulses = 10 + self._wreg(LTR_PS_REG_RATE,0x08) #PS_Measurement_Rate=10ms + self._wreg(LTR_ALS_REG_RATE,0x12) #ALS_Measurement_Rate=200ms,ALS_integration_time=200ms + + def _status(self): + '''数据转换状态''' + status=self._rreg(LTR_553ALS_REG_ATATUS) + return status&0x84, status&0x01 #ALS,PS status + + @property + def getdata(self): + '''处理获取数据''' + if self._status()[0]: + data_als=self._rreg(LTR_ALS_REG_DATA1,4) + als_ch1=data_als[0] | data_als[1]<<8 + als_ch0=data_als[2] | data_als[3]<<8 + ratio=als_ch1/(als_ch1+als_ch0) if (als_ch1+als_ch0)>0 else 0 + self.ALS_IR =als_ch1*ratio/_ALS_GAIN[self.ALS_gain][0] + self.ALS_VIS=als_ch0*ratio/_ALS_GAIN[self.ALS_gain][0] + + if self._status()[1]: + data_ps=self._rreg(LTR_PS_REG_DATA1,2) + self.PS =data_ps[0] | data_ps[1]<<8 + + return round(self.ALS_VIS,2),round(self.ALS_IR,2),self.PS + + def als_vis(self): + '''可见光Lux''' + return self.getdata[0] + + def als_ir(self): + '''红外Lux''' + return self.getdata[1] + + def ps_nl(self): + '''接近距离''' + return self.getdata[2] diff --git a/mixly/boards/default/micropython/build/lib/map.json b/mixly/boards/default/micropython/build/lib/map.json new file mode 100644 index 00000000..cf097e6f --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/map.json @@ -0,0 +1,1110 @@ +{ + "adafruit_miniqr": { + "__require__": [ + "math", + "typing" + ], + "__file__": true, + "__size__": 20917, + "__name__": "adafruit_miniqr.py" + }, + "adxl345": { + "__require__": [ + "time", + "ustruct", + "micropython" + ], + "__file__": true, + "__size__": 1644, + "__name__": "adxl345.py" + }, + "ags10": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 3177, + "__name__": "ags10.py" + }, + "ahtx0": { + "__require__": [ + "utime", + "micropython" + ], + "__file__": true, + "__size__": 3204, + "__name__": "ahtx0.py" + }, + "ap3216c": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 1786, + "__name__": "ap3216c.py" + }, + "apds9960": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 12718, + "__name__": "apds9960.py" + }, + "baidu_speech": { + "__require__": [ + "json", + "gc", + "urequests", + "array", + "ubinascii", + "machine" + ], + "__file__": true, + "__size__": 3703, + "__name__": "baidu_speech.py" + }, + "base64": { + "__require__": [ + "re", + "struct", + "binascii", + "warnings", + "warnings", + "sys", + "getopt" + ], + "__file__": true, + "__size__": 15241, + "__name__": "base64.py" + }, + "ble_advertising": { + "__require__": [ + "micropython", + "struct", + "bluetooth" + ], + "__file__": true, + "__size__": 2492, + "__name__": "ble_advertising.py" + }, + "ble_central": { + "__require__": [ + "time", + "gc", + "bluetooth", + "micropython", + "ubinascii", + "ble_advertising" + ], + "__file__": true, + "__size__": 7391, + "__name__": "ble_central.py" + }, + "ble_handle": { + "__require__": [ + "ble_peripheral" + ], + "__file__": true, + "__size__": 1034, + "__name__": "ble_handle.py" + }, + "ble_hid": { + "__require__": [ + "bluetooth", + "struct", + "time", + "micropython", + "ubinascii", + "ble_advertising", + "bluetooth", + "ble_hid_key" + ], + "__file__": true, + "__size__": 11263, + "__name__": "ble_hid.py" + }, + "ble_hid_keyboard": { + "__require__": [ + "bluetooth", + "struct", + "time", + "micropython", + "ubinascii", + "ble_advertising", + "bluetooth", + "ble_hid_key" + ], + "__file__": true, + "__size__": 9698, + "__name__": "ble_hid_keyboard.py" + }, + "ble_hid_mouse": { + "__require__": [ + "bluetooth", + "struct", + "time", + "micropython", + "ubinascii", + "ble_advertising", + "bluetooth", + "ble_hid_key" + ], + "__file__": true, + "__size__": 8209, + "__name__": "ble_hid_mouse.py" + }, + "ble_peripheral": { + "__require__": [ + "bluetooth", + "micropython", + "ubinascii", + "ble_advertising" + ], + "__file__": true, + "__size__": 2919, + "__name__": "ble_peripheral.py" + }, + "ble_uart_peripheral": { + "__require__": [ + "bluetooth", + "ble_advertising", + "micropython" + ], + "__file__": true, + "__size__": 2846, + "__name__": "ble_uart_peripheral.py" + }, + "ble_uart_repl": { + "__require__": [ + "io", + "os", + "machine", + "micropython", + "ble_uart_peripheral" + ], + "__file__": true, + "__size__": 1824, + "__name__": "ble_uart_repl.py" + }, + "blynklib": { + "__require__": [ + "usocket", + "utime", + "ustruct", + "uselect", + "micropython" + ], + "__file__": true, + "__size__": 14064, + "__name__": "blynklib.py" + }, + "blynktimer": { + "__require__": [ + "time", + "select", + "utime", + "uselect" + ], + "__file__": true, + "__size__": 4600, + "__name__": "blynktimer.py" + }, + "bmp280": { + "__require__": [ + "ustruct", + "utime" + ], + "__file__": true, + "__size__": 6037, + "__name__": "bmp280.py" + }, + "cbr817": { + "__require__": [ + "time", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 3762, + "__name__": "cbr817.py" + }, + "cc_g1": { + "__require__": [ + "micropython", + "machine" + ], + "__file__": true, + "__size__": 2474, + "__name__": "cc_g1.py" + }, + "ch914x_at": { + "__require__": [ + "machine", + "time" + ], + "__file__": true, + "__size__": 4131, + "__name__": "ch914x_at.py" + }, + "ci130x": { + "__require__": [ + "time", + "struct", + "micropython" + ], + "__file__": true, + "__size__": 3722, + "__name__": "ci130x.py" + }, + "debugnet": { + "__require__": [ + "time", + "umqtt", + "ubinascii", + "machine", + "urequests", + "usocket", + "mixiot", + "ussl", + "ujson" + ], + "__file__": true, + "__size__": 5719, + "__name__": "debugnet.py" + }, + "dhtx": { + "__require__": [ + "time", + "machine", + "esp", + "machine" + ], + "__file__": true, + "__size__": 1627, + "__name__": "dhtx.py" + }, + "ds18b20": { + "__require__": [ + "onewire", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 2129, + "__name__": "ds18b20.py" + }, + "expression_picture": { + "__require__": [], + "__file__": true, + "__size__": 31406, + "__name__": "expression_picture.py" + }, + "eye_picture": { + "__require__": [], + "__file__": true, + "__size__": 82105, + "__name__": "eye_picture.py" + }, + "gnss": { + "__require__": [ + "time", + "ubinascii" + ], + "__file__": true, + "__size__": 3335, + "__name__": "gnss.py" + }, + "hmac": { + "__require__": [ + "hashlib", + "binascii" + ], + "__file__": true, + "__size__": 2936, + "__name__": "hmac.py" + }, + "hp203x": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2574, + "__name__": "hp203x.py" + }, + "ht16k33": { + "__require__": [ + "uframebuf", + "micropython" + ], + "__file__": true, + "__size__": 1834, + "__name__": "ht16k33.py" + }, + "huskylens": { + "__require__": [ + "time", + "ubinascii" + ], + "__file__": true, + "__size__": 9047, + "__name__": "huskylens.py" + }, + "hx720": { + "__require__": [ + "time", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 1949, + "__name__": "hx720.py" + }, + "i2cdevice": { + "__require__": [ + "random", + "machine" + ], + "__file__": true, + "__size__": 9852, + "__name__": "i2cdevice.py" + }, + "i2clcd": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2839, + "__name__": "i2clcd.py" + }, + "icm42670": { + "__require__": [ + "time", + "micropython", + "math" + ], + "__file__": true, + "__size__": 3049, + "__name__": "icm42670.py" + }, + "image": { + "__require__": [ + "gc", + "urequests", + "base64", + "jpeg" + ], + "__file__": true, + "__size__": 3626, + "__name__": "image.py" + }, + "informatio_picture": { + "__require__": [], + "__file__": true, + "__size__": 39534, + "__name__": "informatio_picture.py" + }, + "irremote": { + "__require__": [ + "array", + "time", + "gc", + "machine", + "os", + "esp32", + "machine" + ], + "__file__": true, + "__size__": 7002, + "__name__": "irremote.py" + }, + "keypad": { + "__require__": [ + "machine", + "time" + ], + "__file__": true, + "__size__": 1725, + "__name__": "keypad.py" + }, + "ltr308al": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2049, + "__name__": "ltr308al.py" + }, + "ltr381rgb": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2344, + "__name__": "ltr381rgb.py" + }, + "ltr390uv": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2258, + "__name__": "ltr390uv.py" + }, + "ltr553als": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 3221, + "__name__": "ltr553als.py" + }, + "matcher": { + "__require__": [], + "__file__": true, + "__size__": 3336, + "__name__": "matcher.py" + }, + "matrix16x8": { + "__require__": [ + "ht16k33" + ], + "__file__": true, + "__size__": 4107, + "__name__": "matrix16x8.py" + }, + "matrix32x12": { + "__require__": [ + "tm1680" + ], + "__file__": true, + "__size__": 10464, + "__name__": "matrix32x12.py" + }, + "matrix8x5": { + "__require__": [ + "tm1652" + ], + "__file__": true, + "__size__": 1966, + "__name__": "matrix8x5.py" + }, + "max30102": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 11529, + "__name__": "max30102.py" + }, + "mixgo_ai": { + "__require__": [ + "time", + "gc" + ], + "__file__": true, + "__size__": 5845, + "__name__": "mixgo_ai.py" + }, + "mixiot": { + "__require__": [ + "time", + "usocket", + "ustruct", + "machine", + "ubinascii", + "matcher", + "network", + "base64", + "urequests", + "ussl", + "os" + ], + "__file__": true, + "__size__": 12663, + "__name__": "mixiot.py" + }, + "mixpy": { + "__require__": [ + "math", + "urequests", + "json" + ], + "__file__": true, + "__size__": 2892, + "__name__": "mixpy.py" + }, + "mk_pb4023": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2079, + "__name__": "mk_pb4023.py" + }, + "mmc5603": { + "__require__": [ + "time", + "math", + "micropython", + "magnetic_cal" + ], + "__file__": true, + "__size__": 5888, + "__name__": "mmc5603.py" + }, + "mpu9250": { + "__require__": [ + "micropython", + "ustruct", + "time", + "math", + "machine", + "math", + "matrix16x8", + "os", + "compass_cfg", + "compass_cfg" + ], + "__file__": true, + "__size__": 15746, + "__name__": "mpu9250.py" + }, + "ms32006": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 3671, + "__name__": "ms32006.py" + }, + "ms5611": { + "__require__": [ + "utime", + "micropython" + ], + "__file__": true, + "__size__": 2452, + "__name__": "ms5611.py" + }, + "msa301": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 1994, + "__name__": "msa301.py" + }, + "music": { + "__require__": [ + "_thread", + "gc", + "time", + "machine" + ], + "__file__": true, + "__size__": 7346, + "__name__": "music.py" + }, + "mxc6655xa": { + "__require__": [ + "time", + "math", + "micropython", + "math" + ], + "__file__": true, + "__size__": 2818, + "__name__": "mxc6655xa.py" + }, + "ns9300": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 3593, + "__name__": "ns9300.py" + }, + "ntptime": { + "__require__": [ + "utime", + "gc", + "machine", + "usocket", + "ustruct" + ], + "__file__": true, + "__size__": 1729, + "__name__": "ntptime.py" + }, + "object_picture": { + "__require__": [], + "__file__": true, + "__size__": 41926, + "__name__": "object_picture.py" + }, + "oled128x64": { + "__require__": [ + "ssd1106" + ], + "__file__": true, + "__size__": 481, + "__name__": "oled128x64.py" + }, + "ollama": { + "__require__": [ + "urequests", + "time", + "json" + ], + "__file__": true, + "__size__": 3477, + "__name__": "ollama.py" + }, + "onenet": { + "__require__": [ + "ujson", + "umqtt" + ], + "__file__": true, + "__size__": 1102, + "__name__": "onenet.py" + }, + "openai": { + "__require__": [ + "urequests", + "time", + "json", + "ollama" + ], + "__file__": true, + "__size__": 1772, + "__name__": "openai.py" + }, + "pe_g1": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 4305, + "__name__": "pe_g1.py" + }, + "pm2_5": { + "__require__": [ + "time" + ], + "__file__": true, + "__size__": 1076, + "__name__": "pm2_5.py" + }, + "progres_picture": { + "__require__": [], + "__file__": true, + "__size__": 77320, + "__name__": "progres_picture.py" + }, + "ps2": { + "__require__": [ + "time", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 3369, + "__name__": "ps2.py" + }, + "qmc5883l": { + "__require__": [ + "math", + "time", + "micropython" + ], + "__file__": true, + "__size__": 7226, + "__name__": "qmc5883l.py" + }, + "qmi8658": { + "__require__": [ + "time", + "math", + "micropython" + ], + "__file__": true, + "__size__": 4784, + "__name__": "qmi8658.py" + }, + "radio": { + "__require__": [ + "ubinascii", + "network", + "esp", + "espnow" + ], + "__file__": true, + "__size__": 5545, + "__name__": "radio.py" + }, + "rc522": { + "__require__": [ + "machine", + "micropython" + ], + "__file__": true, + "__size__": 7526, + "__name__": "rc522.py" + }, + "rfm98": { + "__require__": [ + "gc", + "time", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 8617, + "__name__": "rfm98.py" + }, + "rtctime": { + "__require__": [ + "gc", + "time", + "machine", + "usocket", + "ustruct" + ], + "__file__": true, + "__size__": 2653, + "__name__": "rtctime.py" + }, + "sc7a20": { + "__require__": [ + "time", + "math", + "micropython", + "math" + ], + "__file__": true, + "__size__": 2454, + "__name__": "sc7a20.py" + }, + "sdcard": { + "__require__": [ + "time", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 8738, + "__name__": "sdcard.py" + }, + "seniverse_api": { + "__require__": [ + "json", + "urequests" + ], + "__file__": true, + "__size__": 7264, + "__name__": "seniverse_api.py" + }, + "servo": { + "__require__": [ + "machine" + ], + "__file__": true, + "__size__": 1338, + "__name__": "servo.py" + }, + "sht20": { + "__require__": [ + "struct", + "time" + ], + "__file__": true, + "__size__": 1155, + "__name__": "sht20.py" + }, + "shtc3": { + "__require__": [ + "time", + "micropython", + "struct" + ], + "__file__": true, + "__size__": 3837, + "__name__": "shtc3.py" + }, + "sonar": { + "__require__": [ + "time", + "machine" + ], + "__file__": true, + "__size__": 1103, + "__name__": "sonar.py" + }, + "spl06_001": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 4422, + "__name__": "spl06_001.py" + }, + "ssd1106": { + "__require__": [ + "uframebuf", + "micropython" + ], + "__file__": true, + "__size__": 4247, + "__name__": "ssd1106.py" + }, + "st7735": { + "__require__": [ + "time", + "uframebuf", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 3670, + "__name__": "st7735.py" + }, + "st7789": { + "__require__": [ + "time", + "machine", + "micropython", + "uframebuf", + "ustruct" + ], + "__file__": true, + "__size__": 10458, + "__name__": "st7789.py" + }, + "syn6288": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2622, + "__name__": "syn6288.py" + }, + "tiny_webdb": { + "__require__": [ + "urequests" + ], + "__file__": true, + "__size__": 3179, + "__name__": "tiny_webdb.py" + }, + "tm1637": { + "__require__": [ + "machine", + "time", + "micropython" + ], + "__file__": true, + "__size__": 2714, + "__name__": "tm1637.py" + }, + "tm1650": { + "__require__": [ + "micropython", + "machine" + ], + "__file__": true, + "__size__": 2015, + "__name__": "tm1650.py" + }, + "tm1652": { + "__require__": [ + "time", + "uframebuf", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 2222, + "__name__": "tm1652.py" + }, + "tm1680": { + "__require__": [ + "uframebuf", + "micropython" + ], + "__file__": true, + "__size__": 2226, + "__name__": "tm1680.py" + }, + "tm1931": { + "__require__": [ + "time", + "framebuf", + "machine", + "micropython" + ], + "__file__": true, + "__size__": 1916, + "__name__": "tm1931.py" + }, + "tvoc07s": { + "__require__": [ + "time" + ], + "__file__": true, + "__size__": 1093, + "__name__": "tvoc07s.py" + }, + "uart_com": { + "__require__": [], + "__file__": true, + "__size__": 588, + "__name__": "uart_com.py" + }, + "ucs12071": { + "__require__": [ + "time", + "micropython" + ], + "__file__": true, + "__size__": 2378, + "__name__": "ucs12071.py" + }, + "uframebuf": { + "__require__": [ + "esp", + "time", + "gc", + "math", + "framebuf", + "adafruit_miniqr" + ], + "__file__": true, + "__size__": 25611, + "__name__": "uframebuf.py" + }, + "umqtt": { + "__require__": [ + "usocket", + "ustruct", + "ussl" + ], + "__file__": true, + "__size__": 6687, + "__name__": "umqtt.py" + }, + "urequests": { + "__require__": [ + "usocket", + "ujson", + "ssl", + "ujson" + ], + "__file__": true, + "__size__": 4346, + "__name__": "urequests.py" + }, + "urllib": { + "__require__": [ + "ucollections" + ], + "__file__": true, + "__size__": 1123, + "__name__": "urllib.py" + }, + "urllib_parse": { + "__require__": [], + "__file__": true, + "__size__": 6445, + "__name__": "urllib_parse.py" + }, + "vl53l0x": { + "__require__": [ + "micropython", + "ustruct", + "utime" + ], + "__file__": true, + "__size__": 9639, + "__name__": "vl53l0x.py" + }, + "websocket": { + "__require__": [ + "usocket", + "ubinascii", + "urandom", + "ustruct", + "urandom", + "ucollections", + "ssl" + ], + "__file__": true, + "__size__": 7605, + "__name__": "websocket.py" + }, + "ws2812": { + "__require__": [ + "time", + "machine" + ], + "__file__": true, + "__size__": 2374, + "__name__": "ws2812.py" + }, + "ws_lora": { + "__require__": [ + "json", + "rfm98", + "ubinascii", + "machine", + "hp203x" + ], + "__file__": true, + "__size__": 4484, + "__name__": "ws_lora.py" + }, + "ws_solo": { + "__require__": [ + "time", + "math", + "machine" + ], + "__file__": true, + "__size__": 3247, + "__name__": "ws_solo.py" + }, + "xunfei": { + "__require__": [ + "time", + "hmac", + "json", + "hashlib", + "rtctime", + "websocket", + "adc_mic", + "base64", + "urllib" + ], + "__file__": true, + "__size__": 11766, + "__name__": "xunfei.py" + } +} \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/matcher.py b/mixly/boards/default/micropython/build/lib/matcher.py new file mode 100644 index 00000000..5d641ccb --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/matcher.py @@ -0,0 +1,97 @@ +# SPDX-FileCopyrightText: 2017 Yoch +# +# SPDX-License-Identifier: EPL-1.0 + +""" +`matcher` +==================================================================================== + +MQTT topic filter matcher from the Eclipse Project's Paho.MQTT.Python +https://github.com/eclipse/paho.mqtt.python/blob/master/src/paho/mqtt/matcher.py +* Author(s): Yoch (https://github.com/yoch) +""" + + +class MQTTMatcher: + """Intended to manage topic filters including wildcards. + + Internally, MQTTMatcher use a prefix tree (trie) to store + values associated with filters, and has an iter_match() + method to iterate efficiently over all filters that match + some topic name. + """ + + # pylint: disable=too-few-public-methods + class Node: + """Individual node on the MQTT prefix tree.""" + + __slots__ = "children", "content" + + def __init__(self): + self.children = {} + self.content = None + + def __init__(self): + self._root = self.Node() + + def __setitem__(self, key, value): + """Add a topic filter :key to the prefix tree + and associate it to :value""" + node = self._root + for sym in key.split("/"): + node = node.children.setdefault(sym, self.Node()) + node.content = value + + def __getitem__(self, key): + """Retrieve the value associated with some topic filter :key""" + try: + node = self._root + for sym in key.split("/"): + node = node.children[sym] + if node.content is None: + raise KeyError(key) + return node.content + except KeyError: + raise KeyError(key) from None + + def __delitem__(self, key): + """Delete the value associated with some topic filter :key""" + lst = [] + try: + parent, node = None, self._root + for k in key.split("/"): + parent, node = node, node.children[k] + lst.append((parent, k, node)) + node.content = None + except KeyError: + raise KeyError(key) from None + else: # cleanup + for parent, k, node in reversed(lst): + if node.children or node.content is not None: + break + del parent.children[k] + + def iter_match(self, topic): + """Return an iterator on all values associated with filters + that match the :topic""" + lst = topic.split("/") + normal = not topic.startswith("$") + + def rec(node, i=0): + if i == len(lst): + if node.content is not None: + yield node.content + else: + part = lst[i] + if part in node.children: + for content in rec(node.children[part], i + 1): + yield content + if "+" in node.children and (normal or i > 0): + for content in rec(node.children["+"], i + 1): + yield content + if "#" in node.children and (normal or i > 0): + content = node.children["#"].content + if content is not None: + yield content + + return rec(self._root) diff --git a/mixly/boards/default/micropython/build/lib/matrix16x8.py b/mixly/boards/default/micropython/build/lib/matrix16x8.py new file mode 100644 index 00000000..195a49bd --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/matrix16x8.py @@ -0,0 +1,71 @@ +""" +Matrix16x8 Displays + +Micropython library for the HT16K33 Matrix16x8 Displays +======================================================= + +#Preliminary composition 20230411 + +dahanzimin From the Mixly Team +""" +from ht16k33 import HT16K33 + +class Matrix(HT16K33): + """A single matrix.""" + def __init__(self, i2c, address=0x70, brightness=0.3, font="5x8", font_address=0x3A0000, width=16, height=8): + super().__init__(i2c, address, brightness, width, height) + self.font(font) + self.uin_font(font_address) + + """Graph module""" + HEART=b' \x02p\x07\xf8\x0f\xf8\x0f\xf0\x07\xe0\x03\xc0\x01\x80\x00' + HEART_SMALL=b'\x00\x00 \x02p\x07\xf0\x07\xe0\x03\xc0\x01\x80\x00\x00\x00' + HAPPY=b'\x00\x00\x00\x00\x18\x18\x18\x18\x00\x00 \x04@\x02\x80\x01' + SAD=b'\x00\x00\x00\x008\x1c\x04 \x00\x00\x80\x01@\x02 \x04' + SMILE=b'\x00\x00\x18\x18$$\x00\x00\x00\x00 \x04@\x02\x80\x01' + SILLY=b'\x00\x00\x18\x18$$\x18\x18\x00\x00\xc0\x03@\x02\x80\x01' + FABULOUS=b'8\x1cD"|>\x00\x00\x00\x00\xe0\x07 \x04\xc0\x03' + SURPRISED=b'\x00\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x00\x00\x80\x00' + ASLEEP=b'\x00\x00\x00\x00<<\x00\x00\x00\x00\xc0\x03 \x04\xc0\x03' + ANGRY=b'D"(\x14\x10\x08\x00\x00\x80\x01@\x02 \x04\x10\x08' + CONFUSED=b'\x00\x00\xc0\x01 \x02\x00\x02\x00\x01\x80\x00\x00\x00\x80\x00' + NO=b'\x00\x00\x10\x02 \x01\xc0\x00\xc0\x00 \x01\x10\x02\x00\x00' + YES=b'\x00\x00\x00\x10\x00\x08\x00\x04\x10\x02 \x01\xc0\x00\x00\x00' + LEFT_ARROW=b'\x00\x00 \x00\x10\x00\x08\x00\xf4?\x08\x00\x10\x00 \x00' + RIGHT_ARROW=b'\x00\x00\x00\x04\x00\x08\x00\x10\xfc/\x00\x10\x00\x08\x00\x04' + DRESS=b' \x02\xf0\x07`\x03\xc0\x01\xa0\x02P\x05\xa8\n\xf0\x07' + TRANSFORMERS=b'\x00\x00\x80\x00`\x03\xa0\x02\xa0\x02@\x01@\x01 \x02' + SCISSORS=b' \x08`\x0c\xc0\x06\x80\x03\x00\x01\xc0\x06\xa0\n@\x04' + EXIT=b'\x00\x0c\x00\x07\x80\x0e@2\x00\x05@\t\x00\x11\x00 ' + TREE=b'\x80\x00\xc0\x01\xe0\x03\xf0\x07\xf8\x0f\x80\x00\x80\x00\x80\x00' + PACMAN=b'\xf0\x03\x18\x04L\x02\x04\x01\x0c\x02\x18\x04\xf0\x03\x00\x00' + TARGET=b'\x00\x00\x00\x00\x80\x03@\x04@\x05@\x04\x80\x03\x00\x00' + TSHIRT=b' \x04\xd0\x0b\x08\x100\x0c \x04 \x04 \x04\xe0\x07' + ROLLERSKATE=b'\xf0\x00\x90\x00\x90\x07\x10\x08\xf0\x0f(\x148\x1c\x00\x00' + DUCK=b'\xe0\x00\x90\x01\x08\x01<\x01 \x7f \x10\xe0\x0f' + HOUSE=b"\xfc?\x06`\x03\xc0\xe4'$$\xa4$$$$$" + TORTOISE=b'\x80\x01\xa0\x05\xe0\x07\xe0\x07\xe0\x07\xc0\x03 \x04\x00\x00' + BUTTERFLY=b'\x00\x00`\x0c\x90\x12\xe0\x0f\x80\x03@\x05\xa0\n`\x0c' + STICKFIGURE=b'\x80\x00@\x01\x80\x00\xc0\x01\xa0\x02\x80\x00@\x01 \x02' + GHOST=b'\xe0\x03\xb0\x06\xb0\x06\xf0\x07\xb0\x06P\x05\xf0\x0f\xf0\x1f' + PITCHFORK=b'\x00\xf8\x00\x04\x00\x04\xff\xff\x00\x04\x00\x04\x00\xf8\x00\x00' + MUSIC_QUAVERS=b'\x00\x00\x00\x00\x18\x86\x00\x1c' + MUSIC_CROTCHET=b'\x00\x00\xff\x0f\x00\x1e\x00?\x00?\x00>\x00\x1c\x00\x00' + COW=b'\x08\x00\x1e\x00\xfa\x07\xfe\x0f\xfe70F0\x060\x06' + RABBIT=b'\xc0?~@\x01Q>\\\x01Q~@\xc0?\x00\x00' + SQUARE_SMALL=b'\x00\x00\x00\x00\xc0\x03@\x02@\x02\xc0\x03\x00\x00\x00\x00' + SQUARE=b'\xf0\x0f\x10\x08\x10\x08\x10\x08\x10\x08\x10\x08\x10\x08\xf0\x0f' + DIAMOND_SMALL=b'\x00\x00\x00\x00\xc0\x01\xa0\x02@\x01\x80\x00\x00\x00\x00\x00' + DIAMOND=b'\xf0\x07X\r\xec\x1b\xd8\r\xb0\x06`\x03\xc0\x01\x80\x00' + CHESSBOARD=b'\x00\x00\xf8?\xa8*\xf8?\xa8*\xf8?\xa8*\xf8?' + TRIANGLE_LEFT=b'\x00\x00\x00\x01\x80\x01\xc0\x01\xe0\x01\xc0\x01\x80\x01\x00\x01' + TRIANGLE=b'\x00\x00\x80\x01\xc0\x03\xe0\x07\xf0\x0f\xf8\x1f\xfc?\x00\x00' + SNAKE=b'\x00\x0e\x00\n\x00\x0e\xf0\x03\xf8\x03\x1c\x00\x0e\x00\x00\x00' + UMBRELLA=b'\x80\x00\xe0\x03\xf0\x07\xf8\x0f\x80\x00\x80\x00\x80\x02\x80\x03' + SKULL=b'\xe0\x03\x90\x04\x88\x08x\x0f\xf0\x07 \x02\xa0\x02\xc0\x01' + GIRAFFE=b'\x80\x01\x80\x03\x80\x00\x80\x00\x80\x00\xf0\x00\x90\x00\x90\x00' + SWORD=b'\x00\x00\x10\x000\x00\xfc\x1f\xfc\x1f0\x00\x10\x00\x00\x00' + DOOR_OPENING=b'\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff' + DOOR_OPEN=b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff' + DOOR_CLOSE=b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' diff --git a/mixly/boards/default/micropython/build/lib/matrix32x12.py b/mixly/boards/default/micropython/build/lib/matrix32x12.py new file mode 100644 index 00000000..d4ad13c7 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/matrix32x12.py @@ -0,0 +1,70 @@ +""" +Matrix Displays + +Micropython library for the TM1680 Matrix Displays +======================================================= + +#Preliminary composition 20230414 + +dahanzimin From the Mixly Team +""" +from tm1680 import TM1680 + +class Matrix(TM1680): + """A single matrix.""" + def __init__(self, i2c, address=0x72, brightness=0.3, font_address=0x3A0000, width=32, height=12): + super().__init__(i2c, address, brightness, width, height) + self.font(font_address) + + """Graph module""" + HEART_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x02\x00\x00p\x07\x00\x00\xf8\x0f\x00\x00\xf8\x0f\x00\x00\xf0\x07\x00\x00\xe0\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + HEART=b'\x00\x00\x00\x00\x00 \x02\x00\x00p\x07\x00\x00\xf8\x0f\x00\x00\xfc\x1f\x00\x00\xfc\x1f\x00\x00\xf8\x0f\x00\x00\xf0\x07\x00\x00\xe0\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00' + HAPPY=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x08\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x00\x00\x00' + SAD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x00\x00\x00' + SMILE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c0\x00\x008\x1c\x00\x00\xe0\x07\x00\x00\x00\x00\x00' + SILLY=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x08\x10\x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x07\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x00\x00\x00' + FABULOUS=b'\x00\x00\x00\x00\x00\x04 \x00\x00\x08\x10\x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x1f\x00\x00\x08\x10\x00\x00\x08\x10\x00\x00\x10\x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00' + SURPRISED=b'\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00' + ASLEEP=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x07\x00\x00\x10\x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00' + ANGRY=b'\x00\x00\x00\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x08\x10\x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x08\x10\x00' + CONFUSED=b'\x00\xc0\x03\x00\x00`\x06\x00\x000\x0c\x00\x000\x0c\x00\x00\x00\x0c\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x80\x01\x00' + NO=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x08\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00' + YES=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x18\x00\x00\x00\x0c\x00\x00\x00\x06\x00\x00\x0c\x03\x00\x00\x98\x01\x00\x00\xf0\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + LEFT_ARROW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00 \x00\x00\x00\x10\x00\x00\x00\xe8\x1f\x00\x00\x10\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + RIGHT_ARROW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\xf8\x17\x00\x00\x00\x08\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DRESS=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x02\x00\x00\xf0\x07\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00P\x05\x00\x00\xa8\n\x00\x00\xf0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TRANSFORMERS=b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xc0\x06\x00\x00@\x05\x00\x00@\x05\x00\x00@\x05\x00\x00\x80\x02\x00\x00\x80\x02\x00\x00@\x04\x00\x00 \x08\x00\x00\x00\x00\x00' + SCISSORS=b'\x00\x00\x00\x00\x00\x04\x10\x00\x00\x0c\x18\x00\x00\x18\x0c\x00\x000\x06\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00p\x07\x00\x00H\t\x00\x00H\t\x00\x000\x06\x00' + EXIT=b'\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\xc0\x01\x00\x00\xa0\x03\x00\x00\x90\x0c\x00\x00\x80\x00\x00\x00P\x01\x00\x00@\x02\x00\x00@\x04\x00\x00\x00\x08\x00\x00\x00\x00\x00' + TREE=b'\x00\x00\x00\x00\x00\x80\x00\x00\x00\xc0\x01\x00\x00\xe0\x03\x00\x00\xf0\x07\x00\x00\xf8\x0f\x00\x00\xfc\x1f\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00' + PACMAN=b'\x00\x00\x00\x00\x00\xf0\x07\x00\x00\x18\x08\x00\x00\x8c\x04\x00\x00\x0c\x02\x00\x00\x04\x01\x00\x00\x0c\x02\x00\x00\x0c\x04\x00\x00\x18\x08\x00\x00\xf0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TARGET=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x07\x00\x00 \x08\x00\x00 \x08\x00\x00 \t\x00\x00 \x08\x00\x00 \x08\x00\x00\xc0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TSHIRT=b'\x00@\x04\x00\x00\xa0\x0b\x00\x00\x10\x10\x00\x00\x08 \x00\x000\x18\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00\xe0\x0f\x00\x00\x00\x00\x00' + ROLLERSKATE=b'\x00\x00\x00\x00\x00\xf8\x00\x00\x00\x88\x00\x00\x00\x88\x00\x00\x00\x88\x0f\x00\x00\x08\x10\x00\x00\x08\x10\x00\x00\xf8\x1f\x00\x00\x14(\x00\x00\x1c8\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DUCK=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x90\x00\x00\x00\x08\x01\x00\x00<\x01\x00\x00 ?\x00\x00 \x10\x00\x00 \x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' + HOUSE=b'\x00\x00\x00\x00\x00\xf0\x0f\x00\x00\x18\x18\x00\x00\x0c0\x00\x00\xd0\x0b\x00\x00P\n\x00\x00P\n\x00\x00\xd0\n\x00\x00P\n\x00\x00P\n\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TORTOISE=b'\x00\x00\x00\x00\x00\x80\x01\x00\x00\xa0\x05\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xc0\x03\x00\x00 \x04\x00\x00\x00\x00\x00' + BUTTERFLY=b'\x00\x00\x00\x00\x00\x18\x0c\x00\x00$\x12\x00\x00D\x11\x00\x00\xf8\x0f\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00\xd0\x05\x00\x00(\n\x00\x00\x18\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00' + STICKFIGURE=b'\x00\x80\x00\x00\x00@\x01\x00\x00@\x01\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00\x90\x04\x00\x00@\x01\x00\x00 \x02\x00\x00\x10\x04\x00\x00\x00\x00\x00' + GHOST=b'\x00\x00\x00\x00\x00\xe0\x03\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00\xf0\x07\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00P\x05\x00\x00\xf0\x0f\x00\x00\xf0\x1f\x00\x00\x00\x00\x00' + PITCHFORK=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\xfc?\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + MUSIC_QUAVERS=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x06\x00\x00x\x0f\x00\x00\xe4=\x00\x00\xc0\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + MUSIC_QUAVER=b'\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00`\x01\x00\x00\xf0\x01\x00\x00\xf8\x01\x00\x00\xf8\x00\x00\x00p\x00\x00' + MUSIC_CROTCHET=b'\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00`\x01\x00\x00\xf0\x01\x00\x00\xf8\x01\x00\x00\xf8\x00\x00\x00p\x00\x00' + COW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00x\x00\x00\x00\xe8\x0f\x00\x00\xf8\x1f\x00\x00\xf8/\x00\x00`,\x00\x00`\x0c\x00\x00`\x0c\x00\x00`\x0c\x00\x00\x00\x00\x00' + RABBIT=b'\x00@\x01\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x000\x06\x00\x00\x10\x04\x00\x00P\x05\x00\x00\x10\x04\x00\x00\x90\x04\x00\x00\xd0\x05\x00\x00\xe0\x03\x00' + SQUARE_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x03\x00\x00@\x02\x00\x00@\x02\x00\x00\xc0\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + SQUARE=b'\x00\xfc?\x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\xfc?\x00' + DIAMOND_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00@\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DIAMOND=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x07\x00\x00X\r\x00\x00\xec\x1b\x00\x00\xd8\r\x00\x00\xb0\x06\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + CHESSBOARD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TRIANGLE_LEFT=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x80\x03\x00\x00\xc0\x03\x00\x00\x80\x03\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TRIANGLE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xe0\x07\x00\x00\xf0\x0f\x00\x00\xf8\x1f\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + SNAKE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00(\x00\x00\x008\x00\x00\xc0\x0f\x00\x00\xe0\x0f\x00\x00p\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + UMBRELLA=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\xe0\x03\x00\x00\xf0\x07\x00\x00\xf8\x0f\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00' + SKULL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x03\x00\x00\x90\x04\x00\x00\x88\x08\x00\x00x\x0f\x00\x00\xf0\x07\x00\x00 \x02\x00\x00 \x02\x00\x00\xa0\x02\x00\x00\xc0\x01\x00\x00\x00\x00\x00' + GIRAFFE=b'\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xe0\x01\x00\x00 \x01\x00\x00 \x01\x00\x00 \x01\x00' + SWORD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x000\x00\x00\x00\xfc\x1f\x00\x00\xfc\x1f\x00\x000\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DOOR_OPEN=b'\x00\xf8\x1f\x00\x00\x04 \x00\x00\x0c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00' + DOOR_OPENING=b'\x00\xf8\x1f\x00\x004 \x00\x00L \x00\x00\x8c \x00\x00\x0c!\x00\x00\x0c!\x00\x00L!\x00\x00L!\x00\x00\x0c!\x00\x00\x0c!\x00\x00\x0c!\x00\x00\x0c!\x00' + DOOR_CLOSE=b'\x00\xf8\x1f\x00\x00\xf4/\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c6\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00' diff --git a/mixly/boards/default/micropython/build/lib/matrix8x5.py b/mixly/boards/default/micropython/build/lib/matrix8x5.py new file mode 100644 index 00000000..d03ae7c9 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/matrix8x5.py @@ -0,0 +1,67 @@ +""" +Matrix8x5 Displays + +Micropython library for the TM1652 Matrix8x5 Displays +======================================================= + +#Preliminary compositio 20230411 + +dahanzimin From the Mixly Team +""" +from tm1652 import TM1652 + +class Matrix(TM1652): + """A single matrix.""" + def __init__(self, pin, brightness=0.3, font="4x5", width=8, height=5): + super().__init__(pin, brightness, width, height) + self.font(font) + + """Graph module 5x8""" + HEART = b'\x14>>\x1c\x08' + HEART_SMALL = b'\x00\x14\x1c\x08\x00' + HAPPY = b'\x00\x14\x00"\x1c' + SAD = b'\x00\x14\x00\x1c"' + SMILE = b'\x00\x14\x00"\x1c' + SILLY = b'"\x00>(8' + FABULOUS = b'>6\x00\x14\x1c' + SURPRISED = b'\x14\x00\x08\x14\x08' + ASLEEP = b'\x006\x00\x1c\x00' + ANGRY = b'"\x14\x00>*' + CONFUSED = b'\x00\x14\x00\x14*' + NO = b'"\x14\x08\x14"' + YES = b'\x00 \x10\n\x04' + LEFT_ARROW = b'\x08\x04~\x04\x08' + RIGHT_ARROW = b'\x10 ~ \x10' + DRESS = b'$f\x08\x08' + PACMAN = b'<\x16\x0e\x1e<' + TARGET = b'\x08\x1c6\x1c\x08' + TSHIRT = b'6>\x1c\x1c\x1c' + ROLLERSKATE = b'00>>\x14' + DUCK = b'\x0c\x0e<\x1c\x00' + HOUSE = b'\x08\x1c>\x1c\x14' + TORTOISE = b'\x00\x1c>\x14\x00' + BUTTERFLY = b'6>\x08>6' + STICKFIGURE = b'\x08>\x08\x14"' + GHOST = b'>*>>*' + PITCHFORK = b'**>\x08\x08' + MUSIC_QUAVERS = b'<$$66' + MUSIC_QUAVER = b'\x08\x18(\x0e\x0e' + MUSIC_CROTCHET = b'\x08\x08\x08\x0e\x0e' + COW = b'"">\x1c\x08' + RABBIT = b'\n\n\x1e\x16\x1e' + SQUARE_SMALL = b'\x00\x1c\x14\x1c\x00' + SQUARE = b'>""">' + DIAMOND_SMALL = b'\x00\x08\x14\x08\x00' + DIAMOND = b'\x08\x14"\x14\x08' + CHESSBOARD = b'\x14*\x14*\x14' + TRIANGLE_LEFT = b'\x02\x06\n\x12>' + TRIANGLE = b'\x00\x08\x14>\x00' + SNAKE = b'\x066\x14\x1c\x00' + UMBRELLA = b'\x1c>\x08\n\x0c' + SKULL = b'\x1c*>\x1c\x1c' + GIRAFFE = b'\x06\x04\x04\x1c\x14' + SWORD = b'\x08\x08\x08\x1c\x08' diff --git a/mixly/boards/default/micropython/build/lib/max30102.py b/mixly/boards/default/micropython/build/lib/max30102.py new file mode 100644 index 00000000..b2ce1eaa --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/max30102.py @@ -0,0 +1,291 @@ +""" +MAX30102 + +MicroPython library for the MAX30102(bmp_and_spo2) +======================================================= + +#Preliminary composition 20220723 +#base on https://github.com/doug-burrell/max30102.git 20220723 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +# Address of each register. +REG_INTR_STATUS_1 = const(0x00) +REG_INTR_STATUS_2 = const(0x01) +REG_INTR_ENABLE_1 = const(0x02) +REG_INTR_ENABLE_2 = const(0x03) +REG_FIFO_WR_PTR = const(0x04) +REG_OVF_COUNTER = const(0x05) +REG_FIFO_RD_PTR = const(0x06) +REG_FIFO_DATA = const(0x07) +REG_FIFO_CONFIG = const(0x08) +REG_MODE_CONFIG = const(0x09) +REG_SPO2_CONFIG = const(0x0A) +REG_LED1_PA = const(0x0C) +REG_LED2_PA = const(0x0D) +REG_PILOT_PA = const(0x10) +REG_MULTI_LED_CTRL1 = const(0x11) +REG_MULTI_LED_CTRL2 = const(0x12) +REG_TEMP_INTR = const(0x1F) +REG_TEMP_FRAC = const(0x20) +REG_TEMP_CONFIG = const(0x21) +REG_PART_ID = const(0xFF) + +class MAX30102: + def __init__(self, i2c, address=0x57): + """Initiate MAX30102 class ond each function responsible for correct device start-up""" + self._device = i2c + self._address = address + + if self._chip_id() != 0x15: + raise AttributeError("Cannot find a MAX30102") + + self.reset() + time.sleep(1) + self.setup() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(REG_PART_ID) + + def reset(self): + """Set default values of all registers""" + self._wreg(REG_MODE_CONFIG, 0x40) + + def shutdown(self): + """Shutdown the device""" + self._wreg(mode_config, 0x80) # 0b10000000 = 0x80 + + def setup(self,led_mode=0x03): + """Set all registers needed to correct work of sensor""" + self._wreg(REG_INTR_ENABLE_1, 0xC0) # 0xc0 : A_FULL_EN and PPG_RDY_EN = Interrupt will be triggered when + self._wreg(REG_INTR_ENABLE_2, 0x00) # fifo almost full & new fifo data ready + + self._wreg(REG_FIFO_WR_PTR, 0x00) # FIFO_WR_PTR[4:0] + self._wreg(REG_OVF_COUNTER, 0x00) # OVF_COUNTER[4:0] + self._wreg(REG_FIFO_RD_PTR, 0x00) # FIFO_RD_PTR[4:0] + + self._wreg(REG_FIFO_CONFIG, 0x4F) # sample avg = 4, fifo rollover = false, fifo almost full = 17 + self._wreg(REG_MODE_CONFIG, led_mode) # 0x02 for read-only, 0x03 for SpO2 mode, 0x07 multimode LED + self._wreg(REG_SPO2_CONFIG, 0x27) # SPO2_ADC range = 4096nA, SPO2 sample rate = 100Hz, LED pulse-width = 411uS + + self._wreg(REG_LED1_PA, 0x40) # choose value for ~7mA for LED1 + self._wreg(REG_LED2_PA, 0x40) # choose value for ~7mA for LED2 + self._wreg(REG_PILOT_PA, 0x7F) # choose value fro ~25mA for Pilot LED + + def get_data_present(self): + read_ptr = self._rreg(REG_FIFO_RD_PTR) + write_ptr = self._rreg(REG_FIFO_WR_PTR) + if read_ptr == write_ptr: + return 0 + else: + num_samples = write_ptr - read_ptr # account for pointer wrap around + if num_samples < 0: + num_samples += 32 + return num_samples + + def read_fifo(self): + """This function will read the data register""" + reg_INTR1 = self._rreg(REG_INTR_STATUS_1) + reg_INTR2 = self._rreg(REG_INTR_STATUS_2) + d = self._rreg(REG_FIFO_DATA, 6) + + red_led = (d[0] << 16 | d[1] << 8 | d[2]) & 0x03FFFF + ir_led = (d[3] << 16 | d[4] << 8 | d[5]) & 0x03FFFF + return ir_led,red_led + + def read_sequential(self, amount=100): + """This function will read the red-led and ir-led `amount` times""" + red_buf = [] + ir_buf = [] + count = amount + while count > 0: + num_bytes = self.get_data_present() + while num_bytes > 0: + ir, red = self.read_fifo() + red_buf.append(red) + ir_buf.append(ir) + num_bytes -= 1 + count -= 1 + return ir_buf,red_buf + + def temperature(self): + """Read temperature as sum of integer and fraction value """ + self._wreg(REG_TEMP_CONFIG, 0x01) + status = self._rreg(REG_INTR_STATUS_2) + count = 1 + while status != 2 and count < 5: + status = self._rreg(REG_INTR_STATUS_2) + count += 1 + integer = self._rreg(REG_TEMP_INTR) + fraction = self._rreg(REG_TEMP_FRAC) + return round(integer + fraction * 0.0625,2) + + def heartrate(self,amount=5): + bpms = [] + sop2 = [] + for _ in range(amount): + ir_data, red_data=self.read_sequential() + if get_mean(ir_data) < 50000 and get_mean(red_data) < 50000 : + return 0,0 + raw_bpm, valid_bpm, raw_spo2, valid_spo2 = calc_hr_and_spo2(ir_data, red_data) + if valid_bpm: + bpms.append(raw_bpm) + if valid_spo2: + sop2.append(raw_spo2) + bpms_len=len(bpms) + sop2_len=len(sop2) + if bpms_len<=2 or sop2_len<=2: + return 0,0 + else: + return sum(sorted(bpms)[1:bpms_len-1])//(bpms_len-2),round(sum(sorted(sop2)[1:sop2_len-1])/(sop2_len-2),2) + +"""-----------以下心率算法-----------""" + +SAMPLE_FREQ = 25 # 25 samples per second +MA_SIZE = 4 +BUFFER_SIZE = 100 # sampling frequency * 4 + +def get_mean(ls): + return sum(ls)/len(ls) + +def calc_hr_and_spo2(ir_data, red_data): + ir_mean = int(get_mean(ir_data)) + x = [] + for k in ir_data: + x.append((k-ir_mean)*-1) + for i in range(len(x) - MA_SIZE): + x[i] = sum(x[i:i+MA_SIZE]) / MA_SIZE + + n_th = int(get_mean(x)) + n_th = 30 if n_th < 30 else n_th # min allowed + n_th = 60 if n_th > 60 else n_th # max allowed + + ir_valley_locs, n_peaks = find_peaks(x, BUFFER_SIZE, n_th, 4, 15) + peak_interval_sum = 0 + if n_peaks >= 2: + for i in range(1, n_peaks): + peak_interval_sum += (ir_valley_locs[i] - ir_valley_locs[i-1]) + peak_interval_sum = int(peak_interval_sum / (n_peaks - 1)) + hr = int(SAMPLE_FREQ * 60 / peak_interval_sum) + hr_valid = True + else: + hr = -999 + hr_valid = False + + exact_ir_valley_locs_count = n_peaks + for i in range(exact_ir_valley_locs_count): + if ir_valley_locs[i] > BUFFER_SIZE: + spo2 = -999 + spo2_valid = False + return hr, hr_valid, spo2, spo2_valid + i_ratio_count = 0 + ratio = [] + # find max between two valley locations + red_dc_max_index = -1 + ir_dc_max_index = -1 + for k in range(exact_ir_valley_locs_count-1): + red_dc_max = -16777216 + ir_dc_max = -16777216 + if ir_valley_locs[k+1] - ir_valley_locs[k] > 3: + for i in range(ir_valley_locs[k], ir_valley_locs[k+1]): + if ir_data[i] > ir_dc_max: + ir_dc_max = ir_data[i] + ir_dc_max_index = i + if red_data[i] > red_dc_max: + red_dc_max = red_data[i] + red_dc_max_index = i + + red_ac = int((red_data[ir_valley_locs[k+1]] - red_data[ir_valley_locs[k]]) * (red_dc_max_index - ir_valley_locs[k])) + red_ac = red_data[ir_valley_locs[k]] + int(red_ac / (ir_valley_locs[k+1] - ir_valley_locs[k])) + red_ac = red_data[red_dc_max_index] - red_ac # subtract linear DC components from raw + + ir_ac = int((ir_data[ir_valley_locs[k+1]] - ir_data[ir_valley_locs[k]]) * (ir_dc_max_index - ir_valley_locs[k])) + ir_ac = ir_data[ir_valley_locs[k]] + int(ir_ac / (ir_valley_locs[k+1] - ir_valley_locs[k])) + ir_ac = ir_data[ir_dc_max_index] - ir_ac # subtract linear DC components from raw + + nume = red_ac * ir_dc_max + denom = ir_ac * red_dc_max + if (denom > 0 and i_ratio_count < 5) and nume != 0: + ratio.append(int(((nume * 100) & 0xffffffff) / denom)) + i_ratio_count += 1 + # choose median value since PPG signal may vary from beat to beat + ratio = sorted(ratio) # sort to ascending order + mid_index = int(i_ratio_count / 2) + + ratio_ave = 0 + if mid_index > 1: + ratio_ave = int((ratio[mid_index-1] + ratio[mid_index])/2) + else: + if len(ratio) != 0: + ratio_ave = ratio[mid_index] + + if ratio_ave > 2 and ratio_ave < 184: + # -45.060 * ratioAverage * ratioAverage / 10000 + 30.354 * ratioAverage / 100 + 94.845 + spo2 = -45.060 * (ratio_ave**2) / 10000.0 + 30.054 * ratio_ave / 100.0 + 94.845 + spo2_valid = True + else: + spo2 = -999 + spo2_valid = False + + return hr, hr_valid, spo2, spo2_valid + +def find_peaks(x, size, min_height, min_dist, max_num): + """ Find at most MAX_NUM peaks above MIN_HEIGHT separated by at least MIN_DISTANCE""" + ir_valley_locs, n_peaks = find_peaks_above_min_height(x, size, min_height, max_num) + ir_valley_locs, n_peaks = remove_close_peaks(n_peaks, ir_valley_locs, x, min_dist) + n_peaks = min([n_peaks, max_num]) + return ir_valley_locs, n_peaks + +def find_peaks_above_min_height(x, size, min_height, max_num): + """Find all peaks above MIN_HEIGHT """ + i = 0 + n_peaks = 0 + ir_valley_locs = [] # [0 for i in range(max_num)] + while i < size - 1: + if x[i] > min_height and x[i] > x[i-1]: # find the left edge of potential peaks + n_width = 1 + while i + n_width < size - 1 and x[i] == x[i+n_width]: # find flat peaks + n_width += 1 + if x[i] > x[i+n_width] and n_peaks < max_num: # find the right edge of peaks + ir_valley_locs.append(i) + n_peaks += 1 # original uses post increment + i += n_width + 1 + else: + i += n_width + else: + i += 1 + + return ir_valley_locs, n_peaks + +def remove_close_peaks(n_peaks, ir_valley_locs, x, min_dist): + """ Remove peaks separated by less than MIN_DISTANCE""" + sorted_indices = sorted(ir_valley_locs, key=lambda i: x[i]) + sorted_indices.reverse() + + i = -1 + while i < n_peaks: + old_n_peaks = n_peaks + n_peaks = i + 1 + j = i + 1 + while j < old_n_peaks: + n_dist = (sorted_indices[j] - sorted_indices[i]) if i != -1 else (sorted_indices[j] + 1) # lag-zero peak of autocorr is at index -1 + if n_dist > min_dist or n_dist < -1 * min_dist: + sorted_indices[n_peaks] = sorted_indices[j] + n_peaks += 1 # original uses post increment + j += 1 + i += 1 + + sorted_indices[:n_peaks] = sorted(sorted_indices[:n_peaks]) + return sorted_indices, n_peaks diff --git a/mixly/boards/default/micropython/build/lib/mixgo_ai.py b/mixly/boards/default/micropython/build/lib/mixgo_ai.py new file mode 100644 index 00000000..9925315f --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/mixgo_ai.py @@ -0,0 +1,206 @@ +""" +AI COM + +MicroPython library for the AI COM ( for MixGo AI) +======================================================= + +#Preliminary composition 20220905 + +dahanzimin From the Mixly Team +""" + +import time,gc + + +class INFO: + def __init__(self, info1,info2,rect): + self.info1=info1 + self.info2=info2 + self.rect=rect + self.x=None + self.y=None + self.w=None + self.h=None + self.xc=None + self.yc=None + if type(rect) in [tuple,list]: + self.x=rect[0] + self.y=rect[1] + self.w=rect[2] + self.h=rect[3] + self.xc=rect[0]+rect[2]//2 + self.yc=rect[1]+rect[3]//2 + self.type="info" + +class AI: + def __init__(self, uart, quick=False): + self._uart=uart + self._uart.init(baudrate=115200, timeout=500) + self._info=[] + self._sdata=[] + self._removal=quick + if not self._chip_id(): + raise AttributeError("Cannot find a MixGo AI") + + def send(self,data): + eec=0 + buffer=str(data).encode() + for i in range(len(buffer)): + eec^=int(buffer[i]) + eec=0 if eec==10 else eec + self._uart.write(buffer+chr(eec)+b'\n') + + def recv(self,timeout=500,warn=True): + t_star=time.ticks_ms() + while not self._uart.any(): + if time.ticks_diff(time.ticks_ms(), t_star) >timeout: + if warn: + print("Warning: MixGo AI timeout not responding") + return False + buffer = self._uart.readline() + if buffer: + eec=0 + if len(buffer)>=3: + for i in range(len(buffer)-2): + eec^=int(buffer[i]) + if eec==buffer[-2] or buffer[-2]==0: + try: + return eval(buffer[:-2].decode()) + except: + return None + def _chip_id(self): + for _ in range(10): + self.send(["ok",[[],'']]) + if self.recv(1000,False): + return True + + def request(self,func='', para=[], name=None, timeout=1000): + if self._sdata != para: + self._sdata=para if self._removal else None + self.send([func,[para,name]]) + else: + self.send([func,[[],name]]) + + #print(func) + if func in ['ailr','ailt','play','record','asr']: #不需要警告提醒 + data=self.recv(timeout,False) + else: + data=self.recv(timeout,True) + + self._info=[] + if data: + #报错处理 + if "err" in data[0] and type(data[1])==list: + if type(data[1][0]) == IndexError or "Missing parameter" == data[1][0]: + self.send(["ok",[[],name]]) #恢复出厂 + self.send([func,[para,name]]) #在发送参数 + else: + raise RuntimeError("Error from MixGo AI",data[1][0]) + else: + _len=max(len(data[0]),len(data[1])) + for i in range(_len): + if type(data[0][i]) == list: + info1=data[0][i][0] + info2=data[0][i][1] + else: + info1=data[0][i] + info2=None + + if data[1]: + rect=data[1][i] + else: + rect=None + self._info.append(INFO(info1,info2,rect)) + return self._info + + def info_len(self): + return len(self._info) + + def info_number(self,number): + if self.info_len() > number: + return self._info[number] + + def configure(self, tx_pin, rx_pin, restart=False): + info=self.request('start',para=[["uart",tx_pin,rx_pin],restart]) + return info[0].info1 if info else False + + def find_qrcode(self): + info=self.request('qr') + return (info[0].info1,info[0].rect) if info else (None,None) + + def find_barcode(self): + info=self.request('bar') + return (info[0].info1,info[0].rect) if info else (None,None) + + def find_apriltag(self): + info=self.request('tag') + return (info[0].info1,info[0].rect) if info else (None,None) + + def find_qrcodes(self): + return self.request('qr') + + def find_barcodes(self): + return self.request('bar') + + def find_apriltags(self): + return self.request('tag') + + def find_lines(self, threshold=2500, theta_margin=25, rho_margin=25): + return self.request('line', para=[threshold, theta_margin, rho_margin]) + + def find_circles(self, threshold=2500, r_min=2, r_max=100): + return self.request('circle', para=[threshold, r_min, r_max]) + + def find_rects(self, threshold=2500): + return self.request('rect', para=[threshold]) + + def find_colors(self, scale=2): + info=self.request('color', para=[scale]) + if info: + return info[0].info1,info[0].info2 + else: + return None,None + + def color_track(self, lab=[0, 100, 0, 100, 0, 0], pixels_threshold=10, margin=1): + return self.request('ctrace', para=[lab, pixels_threshold, margin]) + + def ailocal_train(self, lsit_names, path="mixgo", number=5, disname='自模型训练'): + info= self.request('ailt', para=[lsit_names, path, number], name=disname) + return info[0].info1 if info else False + + def ailocal_class(self, lsit_names, path="mixgo", disname='自模型识别'): + return self.request('ailr', para=[lsit_names, path], name=disname) + + def yolo_recognize(self, anchor, path, disname='物品识别'): + return self.request('aild', para=[anchor, path], name=disname) + + def led_rgb(self, rgb1=(0,0,0), rgb2=(0,0,0)): + info= self.request('rgb', para=[rgb1, rgb2]) + return info[0].info1 if info else False + + def audio_play(self, bck_pin=12, ws_pin=13, dat_pin=14, path="mixgo.wav", volume=80): + info= self.request('play', para=[[bck_pin, ws_pin, dat_pin], path, volume]) + return info[0].info1 if info else False + + def audio_record(self, sample_rate=16000, path="mixgo.wav", times=5): + info= self.request('record', para=[sample_rate, path, times]) + return info[0].info1 if info else False + + def asr_recognize(self, corpus,threshold=0.1): + clist=[] + for cor in corpus: + clist.append([cor,threshold]) + info=self.request('asr', para=[dict(clist)]) + if info: + return info[0].info1,info[0].info2 + else: + return None,None + + def find_licenseplate(self): + return self.request('alpr') + + def find_20object(self): + return self.request('voc20') + + def face_detect(self): + return self.request('face_d') diff --git a/mixly/boards/default/micropython/build/lib/mixiot.py b/mixly/boards/default/micropython/build/lib/mixiot.py new file mode 100644 index 00000000..6cbf09c6 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/mixiot.py @@ -0,0 +1,353 @@ +import time +import usocket as socket +import ustruct as struct +from machine import unique_id +from ubinascii import hexlify +from matcher import MQTTMatcher + +ADDITIONAL_TOPIC = 'b640a0ce465fa2a4150c36b305c1c11b' +WILL_TOPIC = '9d634e1a156dc0c1611eb4c3cff57276' + +def wlan_connect(ssid='MYSSID', password='MYPASS', timeout=10): + import network + wlan = network.WLAN(network.STA_IF) + if not wlan.active(): + wlan.active(True) + time.sleep(0.5) + if not wlan.isconnected(): + print('connecting to:', ssid, end ="") + try: + wlan.connect(ssid, password) + except: + pass + _num = 0 + while not wlan.isconnected(): + _num += 1 + time.sleep(1) + print('.',end ="") + if _num > timeout: + wlan.active(False) + print('') + import os + if 'c5' in os.uname().machine.lower(): + raise RuntimeError("WiFi connection timeout. Please check the SSID and password") + else: + raise RuntimeError("WiFi connection timeout, Please check the SSID and password (only 2.4GHz networks are supported)") + print('\nnetwork config:', wlan.ifconfig()) + return wlan + +def image_base64(path="mixly.jpg"): + from base64 import b64encode + if isinstance(path, str): + with open(path, 'rb') as f: + _data = f.read() + return 'data:image/{};base64,'.format(path.split('.')[-1]).encode() + b64encode(_data) + else: + return b'data:image/jpg;base64,' + b64encode(path) + +def ntp(url='mixio.mixly.cn'): + import urequests + try: + results=eval(urequests.get('http://{}/time.php'.format(url)).text) + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected",e) + return results + +def init_MQTT_client(address, username, password,MQTT_USR_PRJ): + client = MQTTClient(hexlify(unique_id()), address, 1883, username, password) + client.set_last_will(topic=MQTT_USR_PRJ+WILL_TOPIC, msg=client.client_id, qos=2) + if client.connect()==0: + client.publish(MQTT_USR_PRJ+ADDITIONAL_TOPIC, client.client_id, qos=0) + time.sleep_ms(200) + return client + +# Add by Mixly Team +def str_len(object): + if isinstance(object, str): + return len(object.encode('utf-8')) + else: + return len(object) +##################################################### + +class MQTTException(Exception): + pass + +class MQTTClient: + def __init__(self, client_id, server, port=0, username=None, password=None, keepalive=60, ssl=False, ssl_params={}): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = None + self.server = server + self.addr = socket.getaddrinfo(server, port)[0][-1] + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self._on_message = None + self.username = username + self.password = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + self._on_message_filtered = MQTTMatcher() + self._star_time = time.ticks_ms() + + def _send_str(self, s): + self.sock.write(struct.pack("!H", str_len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, mqtt_topic, callback_method, MQTT_USR_PRJ): + """Registers a callback_method for a specific MQTT topic""" + if mqtt_topic is None or callback_method is None: + raise ValueError("MQTT topic and callback method must both be defined.") + self._on_message_filtered[MQTT_USR_PRJ+mqtt_topic] = callback_method + + def remove_callback(self, mqtt_topic): + """Removes a registered callback method""" + if mqtt_topic is None: + raise ValueError("MQTT Topic must be defined.") + try: + del self._on_message_filtered[mqtt_topic] + except KeyError: + raise KeyError( + "MQTT topic callback not added with add_topic_callback." + ) from None + + @property + def on_message(self): + """Called when a new message has been received on a subscribed topic""" + return self._on_message + + @on_message.setter + def on_message(self, method): + self._on_message = method + + def _handle_on_message(self, client, topic, message): + matched = False + if topic is not None: + for callback in self._on_message_filtered.iter_match(topic): + callback(client, topic.split("/")[-1], message) # on_msg with callback + matched = True + + if not matched and self.on_message: # regular on_message + self.on_message(client, topic.split("/")[-1], message) + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + self.sock = socket.socket() + self.sock.connect(self.addr) + print(self.addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) + msg_header=bytearray([0x10]) + msg = bytearray(b"\x04MQTT\x04\x02\0\0") + msg_length = 12 + str_len(self.client_id) + msg[6] = clean_session << 1 + + if self.username is not None: + msg_length += 2 + str_len(self.username) + 2 + str_len(self.password) + msg[6] |= 0xC0 + if self.keepalive: + assert self.keepalive < 65536 + msg[7] |= self.keepalive >> 8 + msg[8] |= self.keepalive & 0x00FF + if self.lw_topic: + msg_length += 2 + str_len(self.lw_topic) + 2 + str_len(self.lw_msg) + msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 + msg[6] |= self.lw_retain << 5 + + if msg_length > 0x7F: + while msg_length>0: + encoded_byte = msg_length % 0x80 + msg_length = msg_length // 0x80 + if msg_length > 0: + encoded_byte |= 0x80 + msg_header.append(encoded_byte) + msg_header.append(0x00) + else: + msg_header.append(msg_length) + msg_header.append(0x00) + + self.sock.write(msg_header) + self.sock.write(msg) + #print(hexlify(msg_header, ":"), hexlify(msg, ":")) + self._send_str(self.client_id) + if self.lw_topic: + self._send_str(self.lw_topic) + self._send_str(self.lw_msg) + if self.username is not None: + self._send_str(self.username) + self._send_str(self.password) + resp = self.sock.read(4) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + if resp[3] == 1: + raise MQTTException("Unsupported Protocol") + elif resp[3] == 2: + raise MQTTException("Illegal ClientID") + elif resp[3] == 3: + raise MQTTException("Server Unavailable") + elif resp[3] == 4: + raise MQTTException("Invalid username and password format") + elif resp[3] == 5: + raise MQTTException("Unauthorized") + else: + raise MQTTException(resp[3]) + return resp[2] & 1 + + + def disconnect(self,MQTT_USR_PRJ): + #MQTT_USR_PRJ = "{}/{}/".format(self.username,self.project) + self.publish(MQTT_USR_PRJ+WILL_TOPIC, self.client_id, qos=1) + self.sock.write(b"\xe0\0") + self.sock.close() + + def ping(self): + self.sock.write(b"\xc0\0") + + def pingSync(self): + self.ping() + for i in range(0,10): + msg = self.check_msg() + if msg == "PINGRESP": + return True + time.sleep_ms(100) + return False + + def publish(self, topic, msg, retain=False, qos=0): + # msg = pubData(msg) + if "+" in topic or "#" in topic: + raise MQTTException("Publish topic can not contain wildcards.") + # check msg/qos kwargs + if msg is None: + raise MQTTException("Message can not be None.") + if isinstance(msg, (int, float)): + msg = str(msg).encode("ascii") + elif isinstance(msg, str): + msg = str(msg).encode("utf-8") + elif isinstance(msg, bytes): + pass + else: + raise MQTTException("Invalid message data type.") + pkt = bytearray(b"\x30\0\0\0") + pkt[0] |= qos << 1 | retain + sz = 2 + str_len(topic) + str_len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + #print(hex(str_len(pkt)), hexlify(pkt, ":")) + self.sock.settimeout(0.05) + #self.sock.setblocking(True) + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.pid += 1 + pid = self.pid + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + if qos == 1: + while 1: + op = self.wait_msg() + if op == 0x40: + sz = self.sock.read(1) + assert sz == b"\x02" + rcv_pid = self.sock.read(2) + rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid == rcv_pid: + return + elif qos == 2: + assert 0 + + def subscribe(self, topic, qos=0): + #assert self.cb is not None, "Subscribe callback is not set" + pkt = bytearray(b"\x82\0\0\0") + self.pid += 1 + if isinstance(topic, str): + topic=topic.encode() + struct.pack_into("!BH", pkt, 1, 2 + 2 + str_len(topic) + 1, self.pid) + #print(hex(str_len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + while 1: + op = self.wait_msg() + if op == 0x90: + resp = self.sock.read(4) + #print(resp) + assert resp[1] == pkt[2] and resp[2] == pkt[3] + if resp[3] == 0x80: + raise MQTTException(resp[3]) + return + + # Wait for a single incoming MQTT message and process it. + def wait_msg(self): + res = self.sock.read(1) + time.sleep_ms(50) + self.sock.settimeout(0.05) + #self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return "PINGRESP" + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len) + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz) + self._handle_on_message(self, str(topic, "utf-8"), str(msg, "utf-8")) + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + # Checks whether a pending message from server is available. + def check_msg(self): + self.sock.settimeout(0.05) + if time.ticks_diff(time.ticks_ms(), self._star_time) >60000: + self._star_time = time.ticks_ms() + self.ping() + return self.wait_msg() + + def get_server_info(self): + return (self.server, self.username, self.password) diff --git a/mixly/boards/default/micropython/build/lib/mixpy.py b/mixly/boards/default/micropython/build/lib/mixpy.py new file mode 100644 index 00000000..cb27e595 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/mixpy.py @@ -0,0 +1,94 @@ +#coding=utf-8 +import math + +def math_map(v, al, ah, bl, bh): + if al==ah: + return bl + if al < ah: + v = max(min(ah,v),al) + if al > ah: + v = max(min(al,v),ah) + return bl + (bh - bl) * (v - al) / (ah - al) + +def math_mean(myList): + localList = [e for e in myList if type(e) == int or type(e) == float] + if not localList: return + return float(sum(localList)) / len(localList) + +def math_median(myList): + localList = sorted([e for e in myList if type(e) == int or type(e) == float]) + if not localList: return + if len(localList) % 2 == 0: + return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0 + else: + return localList[(len(localList) - 1) // 2] + +def math_modes(some_list): + modes = [] + # Using a lists of [item, count] to keep count rather than dict + # to avoid "unhashable" errors when the counted item is itself a list or dict. + counts = [] + maxCount = 1 + for item in some_list: + found = False + for count in counts: + if count[0] == item: + count[1] += 1 + maxCount = max(maxCount, count[1]) + found = True + if not found: + counts.append([item, 1]) + for counted_item, item_count in counts: + if item_count == maxCount: + modes.append(counted_item) + return modes + +def math_standard_deviation(numbers): + n = len(numbers) + if n == 0: return + mean = float(sum(numbers)) / n + variance = sum((x - mean) ** 2 for x in numbers) / n + return math.sqrt(variance) + +def lists_sort(my_list, type, reverse): + def try_float(s): + try: + return float(s) + except: + return 0 + key_funcs = { + "NUMERIC": try_float, + "TEXT": str, + "IGNORE_CASE": lambda s: str(s).lower() + } + key_func = key_funcs[type] + list_cpy = list(my_list) + return sorted(list_cpy, key=key_func, reverse=reverse) + +def format_content(mydict, cid): + if 'lat' in mydict and 'long' in mydict: + res = '{'+'"lat": "{}", "long": "{}", "clientid": "{}"'.format(mydict.pop('lat'),mydict.pop('long'),cid) + if len(mydict)>0: + res += ', "message": [' + for d in mydict: + res += '{{"label": "{}", "value": "{}"}},'.format(d,mydict[d]) + res = res[:-1] + "]" + res += '}' + return res + else: + print('Invalid Input') + +def format_str(d): + return str(d).replace("'",'"') + + +def analyse_sharekey(url): + import urequests + import json + response = urequests.get(url) + + if response.text == '-1': + raise AttributeError('Invalid share key') + else: + result = json.loads(response.text) + return (result['0'], result['1'], result['2']) \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/mk_pb4023.py b/mixly/boards/default/micropython/build/lib/mk_pb4023.py new file mode 100644 index 00000000..8ff85db2 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/mk_pb4023.py @@ -0,0 +1,74 @@ +""" +MK-PB4023PS&ASL&VC-A01E + +MicroPython library for the MK-PB4023PS&ASL&VC-A01E (PS,ASL,CS) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_MK_SYSM = const(0x80) +_MK_ID = const(0x98) +_MK_DATA = const(0xA0) + +class MK_PB4023: + def __init__(self, i2c_bus, addr=0x39): + self._device = i2c_bus + self._address = addr + if self._rreg(_MK_ID) != 0xA0: + raise AttributeError("Cannot find a MK-PB4023") + self._configure() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes) + + def _configure(self): + '''Configuration Register''' + self._wreg(0X82, 0x80) + self._wreg(0x83, 0x01) + self._wreg(0x84, 0x07) + self._wreg(0x85, 0x0B) + self._wreg(0x86, 0x03) + self._wreg(0x87, 0x1A) + self._wreg(0x89, 0x38) + self._wreg(_MK_SYSM,0x0F) #Enable Register + + def getdata(self): + '''Processing data acquisition''' + _buf = self._rreg(_MK_DATA, 12) + _r = _buf[0] | _buf[1] << 8 + _g = _buf[2] | _buf[3] << 8 + _b = _buf[4] | _buf[5] << 8 + _c = _buf[6] | _buf[7] << 8 + _ir = _buf[8] | _buf[9] << 8 + _ps = _buf[10] | _buf[11] << 8 + return _c, _ir, (_r, _g, _b), _ps + + def color(self): + w, _, (r, g, b), _ = self.getdata() + if w == 0: + return (0, 0, 0) + else: + red = int(pow((int((r / w) * 256) / 255), 2.5) * 255) + green = int(pow((int((g / w) * 256) / 255), 2.5) * 255) + blue = int(pow((int((b / w) * 256) / 255), 2.5) * 255) + return (min(red, 255), min(green, 255), min(blue, 255)) + + def color_raw(self): + return self.getdata()[2] + + def ir(self): + return self.getdata()[1] + + def als(self): + w, ir, (r, g, b), _ = self.getdata() + return round((w + ir + r + g + b) / 17.8, 2) + + def ps(self): + return self.getdata()[3] diff --git a/mixly/boards/default/micropython/build/lib/mmc5603.py b/mixly/boards/default/micropython/build/lib/mmc5603.py new file mode 100644 index 00000000..6446e6c1 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/mmc5603.py @@ -0,0 +1,149 @@ +""" +MMC5603 + +Micropython library for the MMC5603NJ(Magnetic) +======================================================= + +#Preliminary composition 20221017 + +dahanzimin From the Mixly Team +""" +import time,math +from micropython import const + +MMC5603_ADDRESS = const(0x30) + +MMC5603_REG_DATA = const(0x00) +MMC5603_REG_TMP = const(0x09) +MMC5603_REG_ODR = const(0x1A) +MMC5603_REG_CTRL0 = const(0x1B) +MMC5603_REG_CTRL1 = const(0x1C) +MMC5603_REG_CTRL2 = const(0x1D) + +MMC5603_REG_X_THD = const(0x1E) +MMC5603_REG_Y_THD = const(0x1F) +MMC5603_REG_Z_THD = const(0x20) +MMC5603_REG_ST_X_VAL = const(0x27) +MMC5603_REG_DEVICE_ID = const(0x39) + +class MMC5603: + def __init__(self, i2c_bus): + self._device = i2c_bus + self._address = MMC5603_ADDRESS + self.raw_x = 0.0 + self.raw_y = 0.0 + self.raw_z = 0.0 + + if self._chip_id() != 0x10: #Check product ID + raise AttributeError("Cannot find a MMC5603") + try: #Read calibration file + import magnetic_cal + self._offset_x = magnetic_cal._offset_x + self._offset_y = magnetic_cal._offset_y + self._offset_z = magnetic_cal._offset_z + except: + self._offset_x = 524288 + self._offset_y = 524288 + self._offset_z = 524288 + #print("offset:",self._offset_x ,self._offset_y,self._offset_z) + + self._auto_selftest() #Auto self-test registers configuration + self._set() + self._continuous_mode(0x00, 50) #Work mode setting + time.sleep(0.05) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(MMC5603_REG_DEVICE_ID) + + def _auto_selftest(self): + '''Auto self-test registers configuration''' + st_thd_reg=[0,0,0] + st_thr_data=[0,0,0] + #/* Read trim data from reg 0x27-0x29 */ + _buffer=self._rreg(MMC5603_REG_ST_X_VAL,3) + for i in range(0, 3, 1): + st_thr_data[i]=(_buffer[i]-128)*32 + if st_thr_data[i] < 0: + st_thr_data[i]=-st_thr_data[i] + st_thd=(st_thr_data[i]-st_thr_data[i]//5)//8 + if st_thd > 255: + st_thd_reg[i]=0xFF + else: + st_thd_reg[i]=st_thd + #/* Write threshold into the reg 0x1E-0x20 */ + self._wreg(MMC5603_REG_X_THD, st_thd_reg[0]) + self._wreg(MMC5603_REG_Y_THD, st_thd_reg[1]) + self._wreg(MMC5603_REG_Z_THD, st_thd_reg[2]) + + def _set(self): + '''Do SET operation''' + self._wreg(MMC5603_REG_CTRL0, 0X08) + time.sleep(0.005) + + def _continuous_mode(self,bandwith,sampling_rate): + '''Work mode setting''' + self._wreg(MMC5603_REG_CTRL1, bandwith) + self._wreg(MMC5603_REG_ODR, sampling_rate) + self._wreg(MMC5603_REG_CTRL0, 0X80|0X20) + self._wreg(MMC5603_REG_CTRL2, 0x10) + + def getdata(self): + _buf=self._rreg( MMC5603_REG_DATA,9) + #/* Transform to unit Gauss */ + self.raw_x=(_buf[0] << 12) | (_buf[1] << 4) | (_buf[6] >> 4) + self.raw_y=(_buf[2] << 12) | (_buf[3] << 4) | (_buf[7] >> 4) + self.raw_z=(_buf[4] << 12) | (_buf[5] << 4) | (_buf[8] >> 4) + return (-0.0625*(self.raw_x-self._offset_x), -0.0625*(self.raw_y-self._offset_y), -0.0625*(self.raw_z-self._offset_z)) + + def calibrate(self): + print("The magnetic field will be calibrated") + print("Please pick up the board and rotate the '8' shape in the air") + time.sleep(2) + self.getdata() + min_x = max_x = self.raw_x + min_y = max_y = self.raw_y + min_z = max_z = self.raw_z + ticks_start = time.ticks_ms() + while (time.ticks_diff(time.ticks_ms(), ticks_start) < 20000) : + self.getdata() + min_x = min(self.raw_x, min_x) + max_x = max(self.raw_x, max_x) + min_y = min(self.raw_y, min_y) + max_y = max(self.raw_y, max_y) + min_z = min(self.raw_z, min_z) + max_z = max(self.raw_z, max_z) + time.sleep_ms(20) + if time.ticks_diff(time.ticks_ms(), ticks_start) % 20 ==0: + print("=",end ="") + print(" 100%") + self._offset_x = (max_x + min_x) / 2 + self._offset_y = (max_y + min_y) / 2 + self._offset_z = (max_z + min_z) / 2 + print("Save x_offset:{}, y_offset:{}, z_offset:{}".format(self._offset_x,self._offset_y,self._offset_z)) + s_f = open("magnetic_cal.py", "w+") + s_f.write("_offset_x="+str(self._offset_x)+"\n") + s_f.write("_offset_y="+str(self._offset_y)+"\n") + s_f.write("_offset_z="+str(self._offset_z)+"\n") + s_f.close() + time.sleep(2) + + def getstrength(self): + _x,_y,_z=self.getdata() + return (math.sqrt(math.pow(_x, 2) + pow(_y, 2) + pow(_z, 2))) + + def getangle(self,upright=False): + _x,_y,_z=self.getdata() + if upright: #vertical + angle=math.atan2(_z, -_x)*(180 / math.pi) + 180 + 3 + return angle if angle<360 else angle-360 + else: #horizontal + angle=math.atan2(_y, -_x)*(180 / math.pi) + 180 + 3 + return angle if angle<360 else angle-360 diff --git a/mixly/boards/default/micropython/build/lib/mpu9250.py b/mixly/boards/default/micropython/build/lib/mpu9250.py new file mode 100644 index 00000000..da9ec659 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/mpu9250.py @@ -0,0 +1,585 @@ +""" +MicroPython I2C driver for MPU9250 9-axis motion tracking device +""" +from micropython import const +import ustruct +import time +import math +from machine import Pin,SoftI2C + +_GYRO_CONFIG = const(0x1b) +_ACCEL_CONFIG = const(0x1c) +_ACCEL_CONFIG2 = const(0x1d) +_INT_PIN_CFG = const(0x37) +_ACCEL_XOUT_H = const(0x3b) +_ACCEL_XOUT_L = const(0x3c) +_ACCEL_YOUT_H = const(0x3d) +_ACCEL_YOUT_L = const(0x3e) +_ACCEL_ZOUT_H = const(0x3f) +_ACCEL_ZOUT_L= const(0x40) +_TEMP_OUT_H = const(0x41) +_TEMP_OUT_L = const(0x42) +_GYRO_XOUT_H = const(0x43) +_GYRO_XOUT_L = const(0x44) +_GYRO_YOUT_H = const(0x45) +_GYRO_YOUT_L = const(0x46) +_GYRO_ZOUT_H = const(0x47) +_GYRO_ZOUT_L = const(0x48) +_WHO_AM_I = const(0x75) + +#_ACCEL_FS_MASK = const(0b00011000) +ACCEL_FS_SEL_2G = const(0b00000000) +ACCEL_FS_SEL_4G = const(0b00001000) +ACCEL_FS_SEL_8G = const(0b00010000) +ACCEL_FS_SEL_16G = const(0b00011000) + +_ACCEL_SO_2G = 16384 # 1 / 16384 ie. 0.061 mg / digit +_ACCEL_SO_4G = 8192 # 1 / 8192 ie. 0.122 mg / digit +_ACCEL_SO_8G = 4096 # 1 / 4096 ie. 0.244 mg / digit +_ACCEL_SO_16G = 2048 # 1 / 2048 ie. 0.488 mg / digit + +#_GYRO_FS_MASK = const(0b00011000) +GYRO_FS_SEL_250DPS = const(0b00000000) +GYRO_FS_SEL_500DPS = const(0b00001000) +GYRO_FS_SEL_1000DPS = const(0b00010000) +GYRO_FS_SEL_2000DPS = const(0b00011000) + +_GYRO_SO_250DPS = 131 +_GYRO_SO_500DPS = 62.5 +_GYRO_SO_1000DPS = 32.8 +_GYRO_SO_2000DPS = 16.4 + +# Used for enablind and disabling the i2c bypass access +_I2C_BYPASS_MASK = const(0b00000010) +_I2C_BYPASS_EN = const(0b00000010) +_I2C_BYPASS_DIS = const(0b00000000) + +SF_G = 1 +SF_M_S2 = 9.80665 # 1 g = 9.80665 m/s2 ie. standard gravity +SF_DEG_S = 1 +SF_RAD_S = 57.295779578552 # 1 rad/s is 57.295779578552 deg/s + + +_WIA = const(0x00) +_HXL = const(0x03) +_HXH = const(0x04) +_HYL = const(0x05) +_HYH = const(0x06) +_HZL = const(0x07) +_HZH = const(0x08) +_ST2 = const(0x09) +_CNTL1 = const(0x0a) +_ASAX = const(0x10) +_ASAY = const(0x11) +_ASAZ = const(0x12) + +_MODE_POWER_DOWN = 0b00000000 +MODE_SINGLE_MEASURE = 0b00000001 +MODE_CONTINOUS_MEASURE_1 = 0b00000010 # 8Hz +MODE_CONTINOUS_MEASURE_2 = 0b00000110 # 100Hz +MODE_EXTERNAL_TRIGGER_MEASURE = 0b00000100 +_MODE_SELF_TEST = 0b00001000 +_MODE_FUSE_ROM_ACCESS = 0b00001111 + +OUTPUT_14_BIT = 0b00000000 +OUTPUT_16_BIT = 0b00010000 + +_SO_14BIT = 0.6 # per digit when 14bit mode +_SO_16BIT = 0.15 # per digit when 16bit mode + +class MPU6500: + """Class which provides interface to MPU6500 6-axis motion tracking device.""" + def __init__( + self, i2c, address=0x68, + accel_fs=ACCEL_FS_SEL_2G, gyro_fs=GYRO_FS_SEL_250DPS, + accel_sf=SF_M_S2, gyro_sf=SF_RAD_S + ): + self.i2c = i2c + self.address = address + + if 0x71 != self.whoami: + raise RuntimeError("MPU9250 not found in I2C bus.") + + self._accel_so = self._accel_fs(accel_fs) + self._gyro_so = self._gyro_fs(gyro_fs) + self._accel_sf = accel_sf + self._gyro_sf = gyro_sf + + # Enable I2C bypass to access for MPU9250 magnetometer access. + char = self._register_char(_INT_PIN_CFG) + char &= ~_I2C_BYPASS_MASK # clear I2C bits + char |= _I2C_BYPASS_EN + self._register_char(_INT_PIN_CFG, char) + + @property + def temperature(self): + tempbuf=self._register_short(0x41) + return tempbuf/333.87 + 21 # I think + + # @property + def acceleration(self): + so = self._accel_so + sf = self._accel_sf + + xyz = self._register_three_shorts(_ACCEL_XOUT_H) + return tuple([value / so * sf for value in xyz]) + + @property + def gyro(self): + """ X, Y, Z radians per second as floats.""" + so = self._gyro_so + sf = self._gyro_sf + + xyz = self._register_three_shorts(_GYRO_XOUT_H) + return tuple([value / so * sf for value in xyz]) + + @property + def whoami(self): + """ Value of the whoami register. """ + return self._register_char(_WHO_AM_I) + + def _register_short(self, register, value=None, buf=bytearray(2)): + if value is None: + self.i2c.readfrom_mem_into(self.address, register, buf) + return ustruct.unpack(">h", buf)[0] + + ustruct.pack_into(">h", buf, 0, value) + return self.i2c.writeto_mem(self.address, register, buf) + + def _register_three_shorts(self, register, buf=bytearray(6)): + self.i2c.readfrom_mem_into(self.address, register, buf) + return ustruct.unpack(">hhh", buf) + + def _register_char(self, register, value=None, buf=bytearray(1)): + if value is None: + self.i2c.readfrom_mem_into(self.address, register, buf) + return buf[0] + + ustruct.pack_into("= 9: + return True + else: + return False + if choice == 'shake': + if abs(self.mpu6500.acceleration()[0]) >= 9 and abs(self.mpu6500.acceleration()[1]) >= 9 : + return True + else: + return False + if choice == 'up': + if self.mpu6500.acceleration()[1] >= 9: + return True + else: + return False + if choice == 'down': + if self.mpu6500.acceleration()[1] <= -9: + return True + else: + return False + if choice == 'right': + if self.mpu6500.acceleration()[0] <= -9: + return True + else: + return False + if choice == 'left': + if self.mpu6500.acceleration()[0] >= 9: + return True + else: + return False + + @property + def mpu9250_gyro(self): + return self.mpu6500.gyro + + def mpu9250_gyro_x(self): + return self.mpu6500.gyro[0] + + def mpu9250_gyro_y(self): + return self.mpu6500.gyro[1] + + def mpu9250_gyro_z(self): + return self.mpu6500.gyro[2] + + def mpu9250_gyro_values(self): + return self.mpu6500.gyro + + @property + def mpu9250_magnetic(self): + """X, Y, Z axis micro-Tesla (uT) as floats.""" + return self.ak8963.magnetic + + def mpu9250_magnetic_x(self): + return self.mpu9250_magnetic[0] + + def mpu9250_magnetic_y(self): + return self.mpu9250_magnetic[1] + + def mpu9250_magnetic_z(self): + return self.mpu9250_magnetic[2] + + def mpu9250_magnetic_values(self): + return self.mpu9250_magnetic + + # @property + def mpu9250_get_field_strength(self): + x=self.mpu9250_magnetic[0] + y=self.mpu9250_magnetic[1] + z=self.mpu9250_magnetic[2] + return (x**2+y**2+z**2)**0.5*1000 + + def mpu9250_heading(self): + x=self.mpu9250_magnetic[0] + y=self.mpu9250_magnetic[1] + z=self.mpu9250_magnetic[2] + a=math.atan(z/x) + b=math.atan(z/y) + xr=x*math.cos(a)+y*math.sin(a)*math.sin(b)-z*math.cos(b)*math.sin(a) + yr=x*math.cos(b)+z*math.sin(b) + return 60*math.atan(yr/xr) + + @property + def whoami(self): + return self.mpu6500.whoami + + def __enter__(self): + return self + + def __exit__(self, exception_type, exception_value, traceback): + pass + +class Compass: + RAD_TO_DEG = 57.295779513082320876798154814105 + + def __init__(self, sensor): + self.sensor = sensor + + def get_x(self): + return self.sensor.mpu9250_magnetic[0] + + def get_y(self): + return self.sensor.mpu9250_magnetic[1] + + def get_z(self): + return self.sensor.mpu9250_magnetic[2] + + def get_field_strength(self): + return self.sensor.mpu9250_get_field_strength() + + def heading(self): + from math import atan2 + xyz = self.sensor.mpu9250_magnetic + return int(((atan2(xyz[1], xyz[0]) * Compass.RAD_TO_DEG) + 180) % 360) + + def calibrate(self): + import matrix16x8 + mp_i2c=SoftI2C(scl = Pin(7), sda = Pin(6), freq = 400000) + mp_matrix = matrix32x12.Matrix(mp_i2c) + if self.is_calibrate() is False: + # print('The calibration need to shaking in the air (e.g. 8 or 0) and waiting for a moment') + print('First write 8 or 0 in the air with the board about 30 seconds, and then try to rotate the board in different direnctions several times.') + mp_matrix.pixel(7, 3, 1) + #mp_matrix.blink_rate(2) + l1=0 + l2=0 + l3=0 + l4=0 + l5=0 + l6=0 + l7=0 + l8=0 + while True: + x = self.sensor.mpu6500.acceleration()[0] + y = self.sensor.mpu6500.acceleration()[1] + z = self.sensor.mpu6500.acceleration()[2] + a=(x**2+y**2+z**2)**0.5 + if z > 0: + if x > 0 and y > 0 and a >= 12: + l1=l1 + 1 + if x > 0 and y < 0 and a >= 12: + l2=l2 + 1 + if x < 0 and y > 0 and a >= 12: + l3=l3 + 1 + if x < 0 and y < 0 and a >= 12: + l4=l4 + 1 + if z < 0: + if x > 0 and y > 0 and a >= 12: + l5=l5 + 1 + if x > 0 and y < 0 and a >= 12: + l6=l6 + 1 + if x < 0 and y > 0 and a >= 12: + l7=l7 + 1 + if x < 0 and y < 0 and a >= 12: + l8=l8 + 1 + if l1 >= 2: + mp_matrix.pixel(7, 0, 1) + mp_matrix.pixel(8, 0, 1) + mp_matrix.pixel(9, 1, 1) + if l2 >= 2: + mp_matrix.pixel(10, 2, 1) + mp_matrix.pixel(10, 3, 1) + if l3 >= 2: + mp_matrix.pixel(10, 4, 1) + mp_matrix.pixel(10, 5, 1) + if l4 >= 2: + mp_matrix.pixel(9, 6, 1) + mp_matrix.pixel(8, 7, 1) + if l5 >= 2: + mp_matrix.pixel(7, 7, 1) + mp_matrix.pixel(6, 7, 1) + if l6 >= 2: + mp_matrix.pixel(5, 6, 1) + mp_matrix.pixel(4, 5, 1) + if l7 >= 2: + mp_matrix.pixel(4, 4, 1) + mp_matrix.pixel(4, 3, 1) + if l8 >= 2: + mp_matrix.pixel(4, 2, 1) + mp_matrix.pixel(5, 1, 1) + mp_matrix.pixel(6, 0, 1) + if l1>=2 and l2>=2 and l3>=2 and l4>=2 and l5>=2 and l6>=2 and l7>=2 and l8>=2: + break + else: + self.sensor.ak8963.calibrate() + with open("compass_cfg.py", "w") as f: + f.write('\n_offset = ' + str(self.sensor.ak8963._offset) + '\n_scale = ' + str(self.sensor.ak8963._offset)) + else: + print('The calibration configuration already exists. If you need to recalibrate, enter os.remove("compass_cfg.py") in repl and restart') + try: + import compass_cfg + self.sensor.ak8963._offset = compass_cfg._offset + self.sensor.ak8963._scale = compass_cfg._scale + except Exception as e: + print('compass_cfg error! delete it, please.') + with open("compass_cfg.py") as f: + for line in f: + print(line) + + def is_calibrate(self): + try: + import compass_cfg + return True + except Exception as e: + return False + + def reset_calibrate(self): + import os + os.remove("compass_cfg.py") diff --git a/mixly/boards/default/micropython/build/lib/ms32006.py b/mixly/boards/default/micropython/build/lib/ms32006.py new file mode 100644 index 00000000..fc1cc71a --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ms32006.py @@ -0,0 +1,137 @@ +""" +MS32006 + +Micropython library for the MS32006 step diever +======================================================= +#Changed from circuitpython to micropython 20211206 +#Fix register read / write bug 20211215 +dahanzimin From the Mixly Team + +""" +import time +from micropython import const + + +MS32006_REG_RESET = const(0x00) #复位 +MS32006_FCLK = const(25000000) #芯片输入时钟选择,此参数与运动速度有关。 范围是:5-30MHZ + +ADDRESS_A = 0x10 +ADDRESS_B = 0x18 +MOT_FULL = 0 +MOT_HALF = 1 +MOT_A = 0 +MOT_B = 4 +MOT_N = 0 +MOT_CW = 1 +MOT_CCW = 2 +MOT_P = 3 +class MS32006: + + _buffer = bytearray(2) + + def __init__(self, i2c_bus,addr=ADDRESS_A,mode=MOT_FULL): + self._device = i2c_bus + self._address = addr + self.reset() + self.mode=mode + + + def _read_u8(self, reg): + return self._device.readfrom_mem(self._address, reg, 1)[0] + + def _write_u8(self, reg, val): + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def reset(self): + self._write_u8(MS32006_REG_RESET,0x00) + time.sleep(0.1) + self._write_u8(MS32006_REG_RESET,0xC1) + + def move(self,moto,mot_dir,mot_pps,mot_step): + readstate_0H = self._read_u8(0x00) + readstate_9H = self._read_u8(0x09) + speed_data=MS32006_FCLK//mot_pps//128 #设置速度 xx pps 128是固定参数 + + if speed_data<32: #限定转速 + speed_data=32 + elif speed_data>16383: + speed_data=16383 + + mot_speed_l=speed_data&0x00ff #取低8位 + mot_speed_h=speed_data//0x100 #取高6位 + + if self.mode==MOT_FULL: #设置整步、半步驱动模式 + mot_speed_h|=0x80 + else: + mot_speed_h&=0x7f + + if mot_step>2047: + raise AttributeError("Reach the set upper limit, up to 2047 step") + + mot_step_l=mot_step&0x00ff + mot_step_h=mot_step//0x100 + mot_step_h|=0x80 + + if mot_dir==MOT_CW: + mot_step_h&=0xBF + else: + mot_step_h|=0x40 + self._write_u8(0x01+moto,mot_speed_l) + self._write_u8(0x02+moto,mot_speed_h) + self._write_u8(0x03+moto,mot_step_l) + self._write_u8(0x04+moto,mot_step_h) + + if moto==MOT_A: + self._write_u8(0x00, readstate_0H&0xfb) + self._write_u8(0x09, readstate_9H|0x80) + else: + self._write_u8(0x00, readstate_0H&0xfd) + self._write_u8(0x09, readstate_9H|0x40) + + def close(self,moto): #停止并关闭输出 + if moto==MOT_A: + self._write_u8(0x04,0x00) + else: + self._write_u8(0x08,0x00) + + def stop(self,moto): #此停止函数,强制让电机停止 + readstate = self._read_u8(0x00) + if moto==MOT_A: + self._write_u8(0x00,readstate|0x04) + else: + self._write_u8(0x00,readstate|0x02) + + def readstep(self,moto): #读取电机运动步数 + if moto==MOT_A: + rdb =self._read_u8(0x0b) + rdc =self._read_u8(0x0c) + else: + rdb =self._read_u8(0x0d) + rdc =self._read_u8(0x0e) + return (rdb*0x100+rdc)&0xfff + + def readbusy(self,moto): #读取电机缓存是否有数据 + if moto==MOT_A: + busy =(self._read_u8(0x0b)>>6)&1 + else: + busy =(self._read_u8(0x0d)>>6)&1 + return bool(busy) + + def readwork(self,moto): #读取电机是否在运行 + if moto==MOT_A: + busy =(self._read_u8(0x0b)>>4)&1 + else: + busy =(self._read_u8(0x0d)>>4)&1 + return bool(busy) + + def dc_motor(self,state,speed=100): #直流电机驱动 + if (state==MOT_CW) | (state==MOT_CCW) : + speed_st=speed*127//100 |0x80 + self._write_u8(0x0A,speed_st) + + readstate = self._read_u8(0x09) & 0xA0 + state_st=(state<<2) | 0X03 | readstate + self._write_u8(0x09,state_st) + + + \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/ms5611.py b/mixly/boards/default/micropython/build/lib/ms5611.py new file mode 100644 index 00000000..ce3f48e1 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ms5611.py @@ -0,0 +1,81 @@ +import utime +from micropython import const + +_MS5611_ADDR = const(0x77) +_CMD_ADC_READ = const(0x00) +_CMD_RESET = const(0x1E) +_CMD_CONVERT_D1 = const(0x40) +_CMD_CONVERT_D2 = const(0x50) +_CAL_DATA_C1 = const(0xA2) +_CAL_DATA_C2 = const(0xA4) +_CAL_DATA_C3 = const(0xA6) +_CAL_DATA_C4 = const(0xA8) +_CAL_DATA_C5 = const(0xAA) +_CAL_DATA_C6 = const(0xAC) + +# Oversampling settings +OSR={"OSR_256":0, "OSR_512":2, "OSR_1024":4, "OSR_2048":6, "OSR_4096":8} + +class MS5611: + def __init__(self, i2c_bus, addr=_MS5611_ADDR, osr='OSR_4096'): + self._device = i2c_bus + self._address = addr + self._wreg(_CMD_RESET) + utime.sleep_ms(50) + + self.c1 = self._rreg(_CAL_DATA_C1, 2) + self.c2 = self._rreg(_CAL_DATA_C2, 2) + self.c3 = self._rreg(_CAL_DATA_C3, 2) + self.c4 = self._rreg(_CAL_DATA_C4, 2) + self.c5 = self._rreg(_CAL_DATA_C5, 2) + self.c6 = self._rreg(_CAL_DATA_C6, 2) + self.pressure_cmd_rate = _CMD_CONVERT_D1 + OSR[osr] + self.temp_cmd_rate = _CMD_CONVERT_D2 + OSR[osr] + + def _wreg(self, val): + '''Write memory address''' + self._device.writeto(self._address, bytes([val])) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return int.from_bytes(self._device.readfrom_mem(self._address, reg, nbytes), 'big') + + @property + def getdata(self): + '''处理获取数据''' + self._wreg(self.pressure_cmd_rate) + utime.sleep_ms(15) + D1 = self._rreg(_CMD_ADC_READ, 3) + + self._wreg(self.temp_cmd_rate) + utime.sleep_ms(15) + D2 = self._rreg(_CMD_ADC_READ, 3) + + dT = D2 - self.c5 * 2 ** 8 + TEMP = 2000 + dT * self.c6 / 2 ** 23 + OFF = self.c2 * 2 ** 16 + dT * self.c4 / 2 ** 7 + SENS = self.c1 * 2 ** 15 + dT * self.c3 / 2 ** 8 + + if TEMP < 2000: + T2 = dT * dT / 2 ** 31 + OFF2 = 5 * (TEMP - 2000) ** 2 / 2 + SENS2 = 5 * (TEMP - 2000) ** 2 / 4 + if TEMP < -1500: + OFF2 = OFF2 + 7 * (TEMP + 1500) ** 2 + SENS2 = SENS2 + 11 * (TEMP + 1500) ** 2 / 2 + TEMP = TEMP - T2 + OFF = OFF - OFF2 + SENS = SENS - SENS2 + + P = (D1 * SENS / 2 ** 21 - OFF) / 2 ** 15 + H = (1 - (P / 101325) ** (1 / 5.255)) * 44330 + return round(P / 100, 2), round(TEMP / 100, 2), round(H, 2) + + def pressure(self): + return self.getdata[0] + + def temperature(self): + return self.getdata[1] + + def altitude(self, reference=1013.25): + return (pow((reference / 33.8639), 0.190255) - pow((self.getdata[0] / 33.8639), 0.190255)) / 0.000013125214 diff --git a/mixly/boards/default/micropython/build/lib/msa301.py b/mixly/boards/default/micropython/build/lib/msa301.py new file mode 100644 index 00000000..c677e1cb --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/msa301.py @@ -0,0 +1,57 @@ +""" +MSA301 + +Micropython library for the MSA301 Accelerometer +======================================================= +#Preliminary composition 20220817 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +MSA301_ADDRESS = const(0x26) +MSA301_REG_DEVICE_ID = const(0x01) +MSA301_REG_DATA = const(0x02) +MSA301_REG_ODR = const(0x10) +MSA301_REG_POWERMODE = const(0x11) +MSA301_REG_RESRANGE = const(0x0F) + +class MSA301: + def __init__(self, i2c_bus, front=False): + self._device = i2c_bus + self._address = MSA301_ADDRESS + self._front = front + if self._chip_id() != 0x13: + raise AttributeError("Cannot find a MSA301") + + self._wreg(MSA301_REG_ODR,0X09) #RATE_500_HZ + self._wreg(MSA301_REG_POWERMODE,0X12) #NORMAL & WIDTH_250_HZ + self._wreg(MSA301_REG_RESRANGE,0X02) #RESOLUTION_14_BIT & RANGE_8_G + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _chip_id(self): + return self._rreg(MSA301_REG_DEVICE_ID) + + def u2s(self,n): + return n if n < (1 << 7) else n - (1 << 8) + + def acceleration(self): + data_reg=self._rreg(MSA301_REG_DATA,6) + x_acc=((self.u2s(data_reg[1])<<8|data_reg[0])>>2)/1024.0 + y_acc=((self.u2s(data_reg[3])<<8|data_reg[2])>>2)/1024.0 + z_acc=((self.u2s(data_reg[5])<<8|data_reg[4])>>2)/1024.0 + return (-y_acc,-x_acc,z_acc) if self._front else (y_acc,-x_acc,z_acc) + + def eulerangles(self,upright=False): + x,y,z=self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default/micropython/build/lib/music.py b/mixly/boards/default/micropython/build/lib/music.py new file mode 100644 index 00000000..7528ad36 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/music.py @@ -0,0 +1,174 @@ +""" +Music buzzer + +Micropython library for the Music buzzer +======================================================= +@dahanzimin From the Mixly Team +""" +import _thread, gc +from time import sleep_ms +from machine import Pin, PWM + +normal_tone = { + 'A1': 55, 'B1': 62, 'C1': 33, 'D1': 37, 'E1': 41, 'F1': 44, 'G1': 49, + 'A2': 110, 'B2': 123, 'C2': 65, 'D2': 73, 'E2': 82, 'F2': 87, 'G2': 98, + 'A3': 220, 'B3': 247, 'C3': 131, 'D3': 147, 'E3': 165, 'F3': 175, 'G3': 196, + 'A4': 440, 'B4': 494, 'C4': 262, 'D4': 294, 'E4': 330, 'F4': 349, 'G4': 392, + 'A5': 880, 'B5': 988, 'C5': 523, 'D5': 587, 'E5': 659, 'F5': 698, 'G5': 784, + 'A6': 1760, 'B6': 1976, 'C6': 1047, 'D6': 1175, 'E6': 1319, 'F6': 1397, 'G6': 1568, + 'A7': 3520, 'B7': 3951, 'C7': 2093, 'D7': 2349, 'E7': 2637, 'F7': 2794, 'G7': 3135, + 'A8': 7040, 'B8': 7902, 'C8': 4186, 'D8': 4699, 'E8': 5274, 'F8': 5588, 'G8': 6271, + 'A9': 14080, 'B9': 15804 } + +Letter = 'ABCDEFG#R' + +class MIDI(): + def __init__(self, pin, volume=100, invert=0, pa_ctrl=None): + self.reset() + self._invert = invert + self._pin = pin + self._volume = volume + self._play = False + self._over = True + self._pwm = None + self._pa_ctrl = pa_ctrl + + def set_volume(self, volume): + if not 0 <= volume <= 100: + raise ValueError("Volume value is in the range: 0-100") + self._volume=volume + + def set_tempo(self, ticks=4, bpm=120): + self.ticks = ticks + self.bpm = bpm + self.beat = 60000 / self.bpm / self.ticks + + def set_octave(self, octave=4): + self.octave = octave + + def set_duration(self, duration=4): + self.duration = duration + + def get_tempo(self): + return (self.ticks, self.bpm) + + def get_octave(self): + return self.octave + + def get_duration(self): + return self.duration + + def reset(self): + self.set_duration() + self.set_octave() + self.set_tempo() + + def parse(self, tone, dict): + time = self.beat * self.duration + pos = tone.find(':') + if pos != -1: + time = self.beat * int(tone[(pos + 1):]) + tone = tone[:pos] + freq, tone_size = 1, len(tone) + if 'R' in tone: + freq = 400000 + elif tone_size == 1: + freq = dict[tone[0] + str(self.octave)] + elif tone_size == 2: + freq = dict[tone] + self.set_octave(tone[1:]) + return int(freq), int(time) + + def midi(self, tone): + pos = tone.find('#') + if pos != -1: + return self.parse(tone.replace('#', ''), normal_tone) + pos = tone.find('B') + if pos != -1 and pos != 0: + return self.parse(tone.replace('B', ''), normal_tone) + return self.parse(tone, normal_tone) + + def set_default(self, tone): + pos = tone.find(':') + if pos != -1: + self.set_duration(int(tone[(pos + 1):])) + tone = tone[:pos] + + def play(self, tune, duration=None, pa_delay=100): + if self._pa_ctrl: self._pa_ctrl(1, pa_delay) + self._pwm = PWM(Pin(self._pin), duty=1023 if self._invert else 0) + self._play = True + self._over = False + if duration is None: + self.set_default(tune[0]) + else: + self.set_duration(duration) + for tone in tune: + tone = tone.upper() + if not self._play: + break + if tone[0] not in Letter: + continue + midi = self.midi(tone) + if self._play: self._pwm.duty((1023-self._volume) if self._invert else self._volume) + if self._play: self._pwm.freq(midi[0]) + sleep_ms(midi[1]) + if self._play: self._pwm.freq(400000) + sleep_ms(1) + if self._pa_ctrl: self._pa_ctrl(0, 0) + self._pwm.deinit() + sleep_ms(10) + self._over = True + + def play_thread(self, tune, duration=None, pa_delay=100): + self._play = False + while not self._over: + sleep_ms(10) + if not self._play: + gc.collect() + _thread.start_new_thread(self.play, (tune, duration, pa_delay)) + sleep_ms(100) + + def pitch(self, freq, pa_delay=100): + if self._pa_ctrl: self._pa_ctrl(1, pa_delay) + self._pwm = PWM(Pin(self._pin)) + self._pwm.duty((1023-self._volume) if self._invert else self._volume) + self._pwm.freq(int(freq)) + + def pitch_time(self, freq, delay, pa_delay=100): + if self._pa_ctrl: self._pa_ctrl(1, pa_delay) + self._pwm = PWM(Pin(self._pin)) + self._pwm.duty((1023-self._volume) if self._invert else self._volume) + self._pwm.freq(int(freq)) + sleep_ms(delay) + if self._pa_ctrl: self._pa_ctrl(0, 0) + self._pwm.deinit() + sleep_ms(10) + + def stop(self): + self._play = False + if self._pa_ctrl: self._pa_ctrl(0, 0) + if self._pwm: self._pwm.deinit() + sleep_ms(10) + + DADADADUM=['r4:2','g','g','g','eb:8','r:2','f','f','f','d:8'] + ENTERTAINER=['d4:1','d#','e','c5:2','e4:1','c5:2','e4:1','c5:3','c:1','d','d#','e','c','d','e:2','b4:1','d5:2','c:4'] + PRELUDE=['c4:1','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e','c4','d','g','d5','f','g4','d5','f','c4','d','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','c4','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e'] + ODE=['e4','e','f','g','g','f','e','d','c','c','d','e','e:6','d:2','d:8','e:4','e','f','g','g','f','e','d','c','c','d','e','d:6','c:2','c:8'] + NYAN=['f#5:1','g#','c#:1','d#:2','b4:1','d5:1','c#','b4:2','b','c#5','d','d:1','c#','b4:1','c#5:1','d#','f#','g#','d#','f#','c#','d','b4','c#5','b4','d#5:2','f#','g#:1','d#','f#','c#','d#','b4','d5','d#','d','c#','b4','c#5','d:2','b4:1','c#5','d#','f#','c#','d','c#','b4','c#5:2','b4','c#5','b4','f#:1','g#','b:2','f#:1','g#','b','c#5','d#','b4','e5','d#','e','f#','b4:2','b','f#:1','g#','b','f#','e5','d#','c#','b4','f#','d#','e','f#','b:2','f#:1','g#','b:2','f#:1','g#','b','b','c#5','d#','b4','f#','g#','f#','b:2','b:1','a#','b','f#','g#','b','e5','d#','e','f#','b4:2','c#5'] + RINGTONE=['c4:1','d','e:2','g','d:1','e','f:2','a','e:1','f','g:2','b','c5:4'] + FUNK=['c2:2','c','d#','c:1','f:2','c:1','f:2','f#','g','c','c','g','c:1','f#:2','c:1','f#:2','f','d#'] + BLUES=['c2:2','e','g','a','a#','a','g','e','c2:2','e','g','a','a#','a','g','e','f','a','c3','d','d#','d','c','a2','c2:2','e','g','a','a#','a','g','e','g','b','d3','f','f2','a','c3','d#','c2:2','e','g','e','g','f','e','d'] + BIRTHDAY=['c4:4','c:1','d:4','c:4','f','e:8','c:3','c:1','d:4','c:4','g','f:8','c:3','c:1','c5:4','a4','f','e','d','a#:3','a#:1','a:4','f','g','f:8'] + WEDDING=['c4:4','f:3','f:1','f:8','c:4','g:3','e:1','f:8','c:4','f:3','a:1','c5:4','a4:3','f:1','f:4','e:3','f:1','g:8'] + FUNERAL=['c3:4','c:3','c:1','c:4','d#:3','d:1','d:3','c:1','c:3','b2:1','c3:4'] + PUNCHLINE=['c4:3','g3:1','f#','g','g#:3','g','r','b','c4'] + PYTHON=['d5:1','b4','r','b','b','a#','b','g5','r','d','d','r','b4','c5','r','c','c','r','d','e:5','c:1','a4','r','a','a','g#','a','f#5','r','e','e','r','c','b4','r','b','b','r','c5','d:5','d:1','b4','r','b','b','a#','b','b5','r','g','g','r','d','c#','r','a','a','r','a','a:5','g:1','f#:2','a:1','a','g#','a','e:2','a:1','a','g#','a','d','r','c#','d','r','c#','d:2','r:3'] + BADDY=['c3:3','r','d:2','d#','r','c','r','f#:8'] + CHASE=['a4:1','b','c5','b4','a:2','r','a:1','b','c5','b4','a:2','r','a:2','e5','d#','e','f','e','d#','e','b4:1','c5','d','c','b4:2','r','b:1','c5','d','c','b4:2','r','b:2','e5','d#','e','f','e','d#','e'] + BA_DING=['b5:1','e6:3'] + WAWAWAWAA=['e3:3','r:1','d#:3','r:1','d:4','r:1','c#:8'] + JUMP_UP=['c5:1','d','e','f','g'] + JUMP_DOWN=['g5:1','f','e','d','c'] + POWER_UP=['g4:1','c5','e4','g5:2','e5:1','g5:3'] + POWER_DOWN=['g5:1','d#','c','g4:2','b:1','c5:3'] diff --git a/mixly/boards/default/micropython/build/lib/mxc6655xa.py b/mixly/boards/default/micropython/build/lib/mxc6655xa.py new file mode 100644 index 00000000..c8884ae5 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/mxc6655xa.py @@ -0,0 +1,91 @@ +""" +MXC6655XA + +Micropython library for the MXC6655XA Accelerometer +======================================================= +#Changed from circuitpython to micropython 20220224 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" +import time +from math import atan,sqrt,degrees +from micropython import const + +MXC6655XA_ADDRESS = const(0x15) +MXC6655XA_REG_DATA = const(0x03) +MXC6655XA_REG_CTRL = const(0x0D) +MXC6655XA_REG_DEVICE_ID = const(0x0E) +MXC6655XA_CMD_8G_POWER_ON = const(0x40) +MXC6655XA_CMD_4G_POWER_ON = const(0x20) +MXC6655XA_CMD_2G_POWER_ON = const(0x00) + +_Range = ( + MXC6655XA_CMD_2G_POWER_ON, # 2g + MXC6655XA_CMD_4G_POWER_ON, # 4g + MXC6655XA_CMD_8G_POWER_ON, # 8g +) + +_Range_X = ( + 1024, # 2g + 512, # 4g + 256, # 8g +) + +MXC6655XA_T_ZERO =25 +MXC6655XA_T_SENSITIVITY =0.586 + +class MXC6655XA: + + def __init__(self,i2c_bus,set_range=2, front=False): + self._device = i2c_bus + self._address = MXC6655XA_ADDRESS + self._range = set_range #default 8g range + self._front = front + + if self._chip_id() != 0x02: + raise AttributeError("Cannot find a MXC6655XA") + self._Enable() #star + #time.sleep(0.3) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(MXC6655XA_REG_DEVICE_ID) + + def _Enable(self): + self._wreg(MXC6655XA_REG_CTRL,_Range[self._range]) + + def u2s(self,n): + return n if n < (1 << 7) else n - (1 << 8) + + @property + def getdata(self): + data_reg=self._rreg(MXC6655XA_REG_DATA,7) + x_acc=float((self.u2s(data_reg[0])<<8|data_reg[1])>>4)/_Range_X[self._range] + y_acc=float((self.u2s(data_reg[2])<<8|data_reg[3])>>4)/_Range_X[self._range] + z_acc=float((self.u2s(data_reg[4])<<8|data_reg[5])>>4)/_Range_X[self._range] + t_acc=float(self.u2s(data_reg[6]))*MXC6655XA_T_SENSITIVITY + MXC6655XA_T_ZERO + return (-y_acc,-x_acc,z_acc,round(t_acc,1)) if self._front else (y_acc,-x_acc,z_acc,round(t_acc,1)) + + def acceleration(self): + return self.getdata[0:3] + + def strength(self): + from math import sqrt + return sqrt(self.getdata[0]**2+self.getdata[1]**2+self.getdata[2]**2) + + def temperature(self): + return self.getdata[3] + + def eulerangles(self,upright=False): + x,y,z=self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default/micropython/build/lib/ns9300.py b/mixly/boards/default/micropython/build/lib/ns9300.py new file mode 100644 index 00000000..3bd5a6e3 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ns9300.py @@ -0,0 +1,117 @@ +""" +NS9300 + +Micropython library for the NS9300(Music Player) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_PLAY_CTRL = const(0x04) +_PLAY_VOL = const(0x06) +_PLAY_INS = const(0x09) +_PLAY_MODE = const(0x0B) + +class NS9300: + def __init__(self, uart, delay=250): + self._uart = uart + self._delay = delay + self._uart.init(baudrate=9600, timeout_char=5) + if not self._chip_id(): + raise AttributeError("Cannot find a NS930x") + + def _wreg(self, cmd, data=b'\x00'): + '''Write memory address''' + _buf = bytearray([cmd, 255 - cmd, len(data)]) + data + eec = 0 + for i in range(len(_buf)): + eec += _buf[i] + _buf.append(eec & 0xFF) + #print("TX:", bytes(_buf), len(_buf)) + self._uart.write(_buf) + + def _rreg(self, cmd): + '''read memory address''' + time.sleep_ms(self._delay) + if self._uart.any(): + _buf = self._uart.read() + #print("RX:", _buf, len(_buf)) + if _buf[0] == 0xAA and _buf[1] == 0x55: + raise OSError("Play Error", _buf[4]) + elif _buf[0] == cmd and _buf[0] == (255 - _buf[1]): + #eec = 0 + #for i in range(len(_buf) - 1): + #eec += _buf[i] + #if (eec & 0xFF) == _buf[-1]: + return _buf[3:3 + _buf[2]] + + def _chip_id(self): + '''复位指令有问题,暂停止播放态处理''' + for _ in range(10): + self._wreg(_PLAY_CTRL, b'\x03') + if self._rreg(_PLAY_CTRL): + return True + + def _ascll(self, data): + '''获取ASCLL字节,剔除中文''' + _strs='' + for char in data: + _strs += char if ord(char) <= 0xFF else "*" + return _strs.encode() + + def status(self, value=1): + """0已停止? 1播放中? 2已暂停?""" + return self.control(0) == value + + def control(self, value=0): + """0查询(0停止 1播放 2暂停) 1播放 2暂停 3停止 4上一曲 5下一曲 6总曲数 7当前曲""" + self._wreg(_PLAY_CTRL, (value if value <= 5 else value + 7).to_bytes(1, 'little')) + _dat = self._rreg(_PLAY_CTRL) + if _dat: + return _dat[1] if value <= 3 else _dat[1] << 8 | _dat[2] + + def play(self, value='m*.mp3'): + """int播放曲目 str播放文件(*省略,GBK编码MPY不支持)""" + if isinstance(value, int): + self._wreg(_PLAY_CTRL, b'\x06' + value.to_bytes(2, 'big')) + elif isinstance(value, str): + self._wreg(_PLAY_CTRL, b'\x07' + self._ascll(value)) + else: + raise ValueError("Input format error") + _dat = self._rreg(_PLAY_CTRL) + if _dat: + return _dat[1] << 8 | _dat[2] + + def insert(self, value='m*.mp3'): + """int播放曲目 str播放文件(*省略,GBK编码MPY不支持)""" + if isinstance(value, int): + self._wreg(_PLAY_INS, b'\x00\x02' + value.to_bytes(2, 'big')) + elif isinstance(value, str): + self._wreg(_PLAY_INS, b'\x01\x02' + self._ascll(value)) + else: + raise ValueError("Input format error") + time.sleep_ms(self._delay) + + def volume(self, value=None): + """None返回音量 int设置音量(0~30)""" + if value is None: + self._wreg(_PLAY_VOL, b'\x00') + _dat = self._rreg(_PLAY_VOL) + if _dat: + return _dat[1] + else: + value = min(30, max(0, value)) + self._wreg(_PLAY_VOL, b'\x01' + value.to_bytes(1, 'little')) + time.sleep_ms(self._delay) + + def mode(self, value=None): + """0全部循环 1单曲循环 2目录循环 3随机播放 4单曲停止 5顺序播放""" + if value is None: + self._wreg(_PLAY_MODE, b'\x00') + _dat = self._rreg(_PLAY_MODE) + if _dat: + return _dat[1] + else: + self._wreg(_PLAY_MODE, b'\x01' + value.to_bytes(1, 'little')) + time.sleep_ms(self._delay) diff --git a/mixly/boards/default/micropython/build/lib/ntptime.py b/mixly/boards/default/micropython/build/lib/ntptime.py new file mode 100644 index 00000000..cce0a4b0 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ntptime.py @@ -0,0 +1,46 @@ +import utime,gc +from machine import RTC +import usocket as socket +import ustruct as struct + +# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 +NTP_DELTA=3155673600 + +def time(host="pool.ntp.org", utc=28800, times=5): + for _ in range(times): + try: + NTP_QUERY = bytearray(48) + NTP_QUERY[0] = 0x1B + addr = socket.getaddrinfo(host, 123)[0][-1] + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.settimeout(1) + res = s.sendto(NTP_QUERY, addr) + msg = s.recv(48) + finally: + del addr + s.close() + gc.collect() + val = struct.unpack("!I", msg[40:44])[0] + return utime.gmtime(val - NTP_DELTA + utc) + except Exception as e: + error = e + utime.sleep(0.1) + raise OSError('Error fetching network time', error) + +# There's currently no timezone support in MicroPython, and the RTC is set in UTC time. +def settime(times): + if isinstance(times, str): + try: + val = eval(times) + if len(val) >= 6: + times=(val[0], val[1], val[2], val[3], val[4], val[5], 0) + else: + raise ValueError("Clock information format error") + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0)) + else: + raise ValueError("Settime needs a tuple of length 6~8") diff --git a/mixly/boards/default/micropython/build/lib/object_picture.py b/mixly/boards/default/micropython/build/lib/object_picture.py new file mode 100644 index 00000000..aae96ce1 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/object_picture.py @@ -0,0 +1,18 @@ +#Take the picture bytes in object_picture.py +#--dahanzimin From the Mixly Team + +Bomb=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x0e\x00\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x02\x00\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x03\x00\x80\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x80\x800\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x80\x80`\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x80\x80\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00A\x01\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00 \x04\x00\x00\x00\x00\x00\x00\x7f\x00\x00@\x11\x18\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x000\x00\x00\x00\x00\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x02\x80\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00#\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x7f\x00\x00\x00@\x00\x06\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x03\xf8\x00\x00\x00\x00\x7f\x00\x00\x06\x00\x00\x01\xf8\x00\x00\x00\x00\x7f\x00\x000\x08\x00\x03\xfc\x00\x00\x00\x00\x7f\x00\x01\xe0\x10\x00\x07\xfc\x00\x00\x00\x00\x7f\x00\x03\x00\x00\x80\x03\xff\xfe\x00\x00\x00\x7f\x00\x00\x000\x00\x03\xff\xff\xc0\x00\x00\x7f\x00\x00\x00 @\x01\xff\xfcp\x00\x00\x7f\x00\x00\x00@@\x03\xff\xff\x18\x00\x00\x7f\x00\x00\x00@@\x03\xff\xff\xcc\x00\x00\x7f\x00\x00\x00\xc0@\x07\xff\xff\xe6\x00\x00\x7f\x00\x00\x00\x00`\x0f\xff\xff\xf3\x00\x00\x7f\x00\x00\x00\x00 \x1f\xff\xff\xf1\x80\x00\x7f\x00\x00\x00\x00 ?\xff\xff\xf9\x80\x00\x7f\x00\x00\x00\x000?\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x000\x7f\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x10\x7f\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00?\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00?\xff\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xff\xff\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xff\xff\xfe\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xff\xfc\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xff\xff\xf8\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\xff\xe0\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xff\xc0\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Boom=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00p\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00X\x00\x0e\x00\x00\x00\x00\x7f\x00\x00\x00\x00x\x00\x16\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\x00:\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xae\x00g\x00\x00\x00\x00\x7f\x00\x00\x80\x01\x96\x00k\x00\x00\x00\x00\x7f\x00\x00\xc0\x01\xab\x81\xd5\x00\x00\x00\x00\x7f\x00\x00|\x03U\xff\xa5\x80\x00\x00\x00\x7f\x00\x00v\x06\xaa\xffU\x80\x00\x00\x00\x7f\x00\x00;\xfe\xa9~\xaa\xc3\x02\x00\x00\x7f\x00\x005\xfdU\x02U`\x0c\x00\x00\x7f\x00\x00\x1a\xaa\xaa\xaa\xaa\xb8x\x00\x04\x7f\x01\x00\x15T\xaa\xaa\xa9_\xf0\x00\x04\x7f\x00\x00\x19URT\xa6\xa2\xb0\x00\x00\x7f\x00\x00\x1a\xaa\xa9J\x95\x15`\x00\x00\x7f\x00\x00\x1a\xaa^\xb5n\xea`\x00\x00\x7f\x00\x009U_\x85\x1e\x15\xc0\x00\x00\x7f\x00\x00:\xaa\xae\xf8{\xea\xc0\x00\x00\x7f\x00\x00z\xaa\xad\x7f\xea\xea\xc0\x00\x00\x7f\x00\x01\xf5U.\xaf\xd5u\x80\x00\x00\x7f\x00\x01\xea\xaa\xadj\xaa\xeb\x80\x00\x00\x7f\x00\x0f\xea\xaa\xae\x95UU\x80\x00\x00\x7f\x07\xff\xaaUUe\xaa\xd5\xc0\x00\x00\x7f\x01\xfe\xaa\xa0\x0e\x9auj\xc0\x00\x00\x7f\x00:\xa9_\xf5\xe3\xea\xd5\xc0\x00\x00\x7f\x00\x0e*\xaf\xea\xdeuU`\x00\x00\x7f\x00\x03\x95V\xaa\x80j\xea\xb0\x00\x00\x7f\x00\x01\xea\xabU\x80j\xb5x\x00\x00\x7f\x00\x00\xea\xa9\xaa\x80*\xba\x9c\x00\x00\x7f\x00\x009U\xd5\x00:\xadW\x00\x00\x7f\x00\x00\x1dT\xd5\x00\x1a\xadW\xe0\x00\x7f\x00\x00\x1c\xa5\xd7\x00\x0e\xb7T\x1e\x00\x7f\x00\x00\x0fU\xdd\xc3\xfdOU\xf8\x00\x7f\x00\x00\x06\xaa\xa2\xe5V\xba\xa5\x80\x00\x7f\x00\x00\x03\xa9\xbe\xba\xaa\xb2W\x00\x00\x7f\x00\x00\x03U\xc1ZUj\xac\x00\x00\x7f\x10\x0c\x03\xab\xbfU\xaaj\xac\x00\x00\x7f\x00\x08\x03\xa5\xfb\xaaU\xaa\xa8\x00\x00\x7f\x00\x00\x03\xd5\xd4\xd5\xaar\x98\x00\x00\x7f\x00\x00\x03\x97UtU\xfdX\x1c\x00\x7f\x00\x00\x03\xa8\xaa{\x97\x92\xa8\x0c\x00\x7f\x00\x00\x03UUW\xf5UX\x00\x00\x7f\x00\x00\x07\xaa\xaa\xbd>\xaaL\x00\x00\x7f\x00\x00\x06>\x95YOS\xec\x00\x00\x7f\x00\x00\r\xff\xca\xba\xaa\xaf\xfa\x00\x00\x7f\x00\x00\x1f\x81\xf5Z\xab_\x0e\x00\x00\x7f\x00\x00\x1e\x00uIT\x9c\x03\x00\x00\x7f\x00\xc00\x00:\xaa\xaa\xb8\x00\x00\x00\x7f\x00\x00@\x00\x1a\xaa\xa2\x98\x00\x00\x04\x7f\x00\x00\x00\x00\tH\xfc\x98\x00\x00\x00\x7f\x00\x00\x00\x10\x0e\xab\xffp\x000\x00\x7f\x00\x00\x00\x00\x05O\x83P@\x10\x00\x7f\x00\x00\x00\x80\x06\xbe\x00\xd0 \x00\x00\x7f\x00\x04\x00\x00\x06\xb8\x00p\x00\x00\x00\x7f\x00\x10\x00\x00\x03p\x000\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xe0\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +DOOR_CLOSE=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x18\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x08\x00\x00\x01\x80\x00\x00\x18\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x11\x8c\x00\x00\x10\x08\x00\x009\x9e\x00\x00\x10\x08\x00\x00y\x9e\x00\x00\x10\x08\x00\x001\x8c\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x001\x8c\x00\x00\x10\x08\x00\x00y\x9e\x00\x00\x10\x08\x00\x009\x9e\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x18\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +DOOR_OPEN=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +DOOR_OPENING=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x08\xff\xff\xff\xff\xff\xff\x10\x08\x07\xff\xff\xff\xff\xe0\x10\x08\x00?\xff\xff\xfc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00?\xff\xff\xfc\x00\x10\x08\x07\xff\xff\xff\xff\xe0\x10\x08\xff\xff\xff\xff\xff\xff\x10\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Fire=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x0f\x00\x00\x00\x00\x00\x7f\x00\x00\x03\x00\x00\x0f\x80\x00\x00\x01\x80\x7f\x00\x00\x03\x80\x00\x0f\x80\x00\x00\x03\x80\x7f\x00\x00\x03\xc0\x00\x0f\xc0\x00\x00\x07\x80\x7f\x00\x00\x07\xe0\x00\x1f\xc0\x00\x00\x07\x80\x7f\x00\x00\x07\xf0\x00\x1f\xc0\x00\x00\x07\xc0\x7f\x00\x00\x0f\xf0\x00?\xc0\x00\x00\x03\xc0\x7f\x00\x00\x0f\xf0\x00\x7f\xc0\x00\x00\x03\xe0\x7f\x00\x00\x1f\xf0\x00\xff\xc0\x00\x00\x03\xe0\x7f\x00\x00\x1f\xf0\x01\xff\xc0\x00\x00\x03\xf0\x7f\x00\x00\x1f\xf0\x07\xff\xc0\x00\x00\x03\xf8\x7f\x00\x00\x1f\xe0\x07\xff\xc0\x00\x00\x03\xfc\x7f\x00\x00\x1f\xe0\x0f\xff\xc0\x00\x00\x03\xfc\x7f\x00\x00\x1f\xe0\x0f\xff\xc0|\x00\x07\xfc\x7f\x00\x00\x0f\xe0\x1f\xff\xc3\xfe\x00\x07\xfc\x7f\x00\x00\x07\xc0\x1f\xff\x87\xfc\x00\x0f\xfc\x7f\x00\x00\x01\xc1\x1f\xff\x8f\xf8\x00?\xfc\x7f\x00\x00\x00\xe3\xbf\xef\x9f\xf8\x00\xff\xfc\x7f\x00\x00\x007\xbf\xef\xdf\xf8\x01\xff\xf8\x7f\x00\x00\x00\x0f\xbf\xdf\xff\xf0\x03\xff\xf8\x7f\x00\x00\x00\x1f\xdf\xdf\xfe\xf0\x07\xff\xf0\x7f\x10\x00\x00\x1f\xff\xdf\xff\xf0\x07\xff\x80\x7f\x18\x00\x00\x1f\xff\xaf\xfd\xf0\x0f\x80\x00\x7f\x1c\x00\x04\x1f\xff\xbf\xfb\xe0\x08\x00\x00\x7f\x1e\x00\x1e\x1f\xff\xdf\xfb\xe0\x00\x00\x00\x7f\x1f\x00>\x1f\xff\xaf\xfb\xe0\x00\x00\x00\x7f\x1f\x80~\x1f\xff\xaf\xf7\xe0\x00\x00\x00\x7f\x1f\xc0\x7f\x1f\xff\xaf\xeb\xe0~\x00\x00\x7f\x1f\xf0\x7f\x1f\xff\xd7\xf7\xe1\xfe\x00\x00\x7f\x1f\xf0\xff\x9f\xff\xab\xeb\xe7\xfc\x00\x00\x7f\x0f\xf8\xff\x8f\xbf\xab\xd7\xef\xf8\x00\x00\x7f\x0f\xf8\xff\xcf\xcf\xd5\xd7\xff\xf8\x0e\x00\x7f\x0f\xf8\xff\xef\xf5\xaa\xab\xffp\x7f\x00\x7f\x07\xfc\xff\xff\xf5UW\xfd\xf1\xfe\x00\x7f\x07\xfc\x7f\xff\xf5J\xab\xfe\xe3\xfc\x00\x7f\x03\xfc\x7f\xff\xfa\xf5U\xfd\xe7\xf8\x00\x7f\x01\xfc\x7f\xff\xfe\x9dU\xf5\xef\xf0\x00\x7f\x00\xfc\x7f\xff\xfdF\xaa\xea\xef\xf0\x00\x7f\x00\x1d\x7f\xb8\x00\x80\x7f\x00\xe0@\x00<\xf0\x1e\xef\xf8\x00\x80\x7f\x00x@\x07=\x00\x1f\xd7\xdc\x00\xc0\x7f\x000\xc0\x00\x10\x00\x00\x04\x00\x00\x08\x7f\x00\x02p\x00\x10\x00\x00\x04\x00\x00\x08\x7f' +Forest=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00~\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00z\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x07\xff\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x0f\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xff\xc0\x00\x00\x00\x00\x06\x00\x00\x7f\x00\x00\xfe\x00\x00\x00\x08\x00\x06\x00\x00\x7f\x00\x03\xff\x00\x00\x00\x0c\x89\x9d\x83\x00\x7f\x00\x0f\xff\x80\x00\x00\x07\x8d\x8b\x0e\x00\x7f\x00\x1f\xff\xc0\x00\x19a\xb0\x04\xc9\x80\x7f\x00?\xff\xf0\x00\x1b\x1aV\x1a\xb3\x90\x7f\x00\x7f\xff\xf0\x00\x06\xef\x84A\x14\x10\x7f\x00\xff\xff\xf8\x00\x1a`\xbb\x14\x8b\x10\x7f\x00\x01\xff\x04\x00P\x1b\x89d\xf4\x06\x7f\x00\x03\xff\x80\x00f\xe2\x91 d\x9e\x7f\x00\x0f\xff\xc0\x00\x018\xeb\xc7\xe0`\x7f\x00\x1f\xff\xf0\x00\xc4\xc1\xa8\xcc\xe1\xa8\x7f\x00?\xff\xf8\x04\xd6}\xb1\x15aL\x7f\x00\x7f\xff\xfe\x0e!/A\xe5`\xb0\x7f\x00\xff\xff\xff\x80\xd4'\x06 o0\x7f\x01\xfd\xff\xc1\xc35[\x06\xb0{\x00\x7f\x03\xe1\xff\xe0\x02\xb1\x13\xc1\xa0\xe10\x7f\x03\x87\xff\xf0\x01\xb0\x01\xe0\x03\xe6\xcc\x7f\x04\x1f\xff\xfc\x000\x03\xf8?\xc4Y\x7f\x00?\xff\xff\x80\x98\x07\xfc\xff\x81\x8b\xff\x00\x7f\xff\xff\xe3d\x1f\xfd\xfc\x01h\x7f\x01\xff\xff\xff\xc0\xe7\xfe?\xc0\x88L\x7f\x07\xff\xff\xfc\x0e\xa1\xf0\x0f\x84\x98\x0c\x7f\x1f\xf7\xff\xf0\x06X\xc0\x0f\x86\n\x00\x7f\x1f\xe7\xff\xf0\x03I\x80\x07\x81\x17\x00\x7f\x00\x07\xff\xf8\x03/@\x07\x81 0\x7f\x00\x0f\xff\xfc\x00\xb4@\x0f\x80\xcd\xe0\x7f\x00?\xff\xfe\x03\xe4\x80\x0f\x86\xc0(\x7f\x00\xff\xff\xff\x02c\x00?\x82\x87\xdc\x7f\x03\xff\xff\xff\x80\xc5\x07\xff\xfd\x8d@\x7f\x07\xe7\xff\xc7\xf0\x16?\xff\xff\xf9\xe0\x7f\x1c\x0f\xff\xe0x\x12\x7f\xfe\x0f\xf8\x80\x7f\x00?\xff\xf0\x00\x11\xff\xf8\x02\x84@\x7f\x00\x7f\xff\xfc\x00\x01\xff\xe0\x02D\xc0\x7f\x00\xff\xff\xfe\x00\x03\xff\x00\x02\xca\x80\x7f\x01\xff?\xff\x80\x07\xfe\x00\x00\x19p\x7f\x03\xfc;\xff\xe0\x07\xfc\x00\x00\x13 \x7f\x0f\xf08\xff\xf8\x0f\xf8\x00\x00\x02\xc0\x7f\x7f\x008\x0f\xff\x1f\xf8\x00\x00\x02\xc0\x7f\x00\x008\x00\x00\x1f\xf8\x00\x00\x00\x00\x7f\x00\x008\x00\x00?\xf8\x00\x00\x00\x00\x7f\x00\x008\x00\x0e\x7f\xf9\x00\x00\x00\x00\x7f\x00\x008\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" +Lightning=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xf0\x18\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xff\xa0\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xff@\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xfe\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xfd\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfb\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfa\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xe8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff`\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfe\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfc\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xf9\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xfa\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xec\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xd8\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xfe\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xfe\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xf8\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xf0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Light_off=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xd5p\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07J\xb8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1c\xb5\\\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1bEV\x00\x00\x00\x00\x7f\x00\x00\x00\x004\n\xab\x00\x00\x00\x00\x7f\x00\x00\x00\x00tUU\x00\x00\x00\x00\x7f\x00\x00\x00\x00h\xaa\xab\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd1UU\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xa2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xa5UU@\x00\x00\x00\x7f\x00\x00\x00\x01\xd2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xa5UU@\x00\x00\x00\x7f\x00\x00\x00\x01\xaa\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UU\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UT\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UW\x80\x00\x00\x00\x7f\x00\x00\x00\x00j\xaa\xa9\x80\x00\x00\x00\x7f\x00\x00\x00\x00eUW\x00\x00\x00\x00\x7f\x00\x00\x00\x00=US\x00\x00\x00\x00\x7f\x00\x00\x00\x002\xaa\xae\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1dUV\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xac\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rU\\\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0e\xaa\xa8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05UX\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\xb8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x90\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06Up\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xaa\xb0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xaa\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x83\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Light_on=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xc0\x00\x0c\x00\x02\x00\x00\x00\x7f\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x0c\x00\x00\x00\x7f\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x7f\x00\x00\x00\x0c\x00\x1e\x000\x00\x00\x00\x7f\x00\x00\x00\x06\x00\xff\xc0`\x00\x00\x00\x7f\x00\x00\x00\x02\x03\x80p\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x100\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x000\xe0\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00a\x80\x01\x00\x00\x00\x00\x7f\x00\x00\x00\x00B\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xc6\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x84\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x8c\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\x8c\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x01\x88\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x00\x00@\xfe\x00\x00\x7f\x00\x00\x7f\xc1\x80\x00\x00A\xfe\x00\x00\x7f\x00\x00\x00\x00\x80\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00@\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x01\x00\x00\x00\x00\x7f\x00\x00\x00\x00 \x00\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x00\x02\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x10\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x04\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x08\x00\x0c\x0c\x00\x00\x00\x7f\x00\x00\x00\x18\x0c\x00\x08\x06\x00\x00\x00\x7f\x00\x00\x000\x04\x00\x08\x03\x00\x00\x00\x7f\x00\x00\x00`\x04\x00\x18\x01\x80\x00\x00\x7f\x00\x00\x00\xc0\x06\x00\x10\x00\xc0\x00\x00\x7f\x00\x00\x01\x80\x06\x00\x10\x00`\x00\x00\x7f\x00\x00\x01\x00\x02\x000\x00 \x00\x00\x7f\x00\x00\x00\x00\x02\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x83\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Night=b'P4\n89 64\n\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\x7f\xff\xff\xff\xfe\x00\x7f\xff\xdf\xff\xff\xf7\xdf\xff\xff\xff\xe0\x00?\xff\xff\xff\xff\xef\xff\xff\xff\xff\x80\x01\xff\xff\xff\xff\x7f\xff\xef\xff\xff\xfe\x00\x07\xff\xff\xff\xff?\xdf\xff\xff\xff\xfc\x00\x0f\xff\xff\xff\xfe\x1f\xff\xff\xff\xff\xf8\x00?\xff\x87\xff\xfe?\xdf\xff\xff\xff\xf0\x00\x7f\xff\xcf\xff\xfe?\xff\xef\xff\xff\xe0\x00\xff\xff\xcf\xff\xff\xff\xef\xdf\xff\xff\xc0\x01\xff\xff\xff\xff\xff\xff\xfb\xbf\xff\xff\x80\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xf9\xff\xff\xff\xff\xff\xfc\x00\x0f\xff\xff\xff\xe0?\xff\xcf\xff\xff\xfc\x00\x1f\xff\xff\xff\xe0?\xff\x87\xff\xff\xfc\x00\x1f\xff\xff\xff\xf0\x7f\xff\x8f\xff\xff\xfc\x00\x1f\xff\xff\xff\xf0\x7f\xff\xcf\xff\xff\xfc\x00\x1f\xff\xff\xff\xf2\x7f\xbf\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xbf\xff\xff\xff\xf8\x00?\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xf5\xfb\xff\xff\xff\xf9\xff\xff\xfc\x00\x1f\xff\xee\xfb\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xee\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xf5\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\x80\x03\xff\xef\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x01\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xf0\x00\x7f\xff\xfc?\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xfe\x00\x1f\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xff\x00\x0f\xff\xe0\x07\xff\xff\xff\xbf\xff\xff\xff\xc0\x03\xff\xf0\x0f\xff\xf7\xff\x0f\xff\xff\xff\xf8\x00\x7f\xf8\x0f\xff\xff\xff\x1f\xff\xff\xff\xff\x83\xff\xf0\x0f\xff\xff\xff\x1f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf3\xcf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x0f\xff\xff\xfd\x7f\xff\xf1\xff\xff\xff\xff\xf8\x1f\xff\xff\xfb\xbf\xff\xf9\xff\xff\xff\xff\xfc?\xff\xff\xfb\xbf?\xff\xff\xff\xff\xff\xfc\x1f\xff\xff\xfd\x7f?\xff\xff\xff\xff\xff\xfd\x9f\xff\xff\xff\xff?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Pirate=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfb\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xf8\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfe`\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xb8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xd8\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xec\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xee\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf6\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf6\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xf9\xff\xe7\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xc0\x7f\x80\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xc0?\x00\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00?\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00?\xc0?\x00\xff\x00\x00\x00\x7f\x00\x00\x00?\xe0s\x81\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xf1\xf1\xe3\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xe1\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xe0\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\x7f\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\x7f\xc0\x00\x00\x00\x7f\x00\x00\xf0\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\xf0\x00\xff\xff\xff\x80\x00\xf0\x00\x7f\x00\x00\xf8\x00\x07\xff\xf8\x00\x01\xf0\x00\x7f\x00\x00\xf8\x00\x07\xff\xf8\x00\x03\xf0\x00\x7f\x00\x01\xff\x00\x07\xf7\xf8\x00\x07\xe0\x00\x7f\x00\x03\xff\xe0\x06s\x98\x00?\xf0\x00\x7f\x00\x03\xff\xfe\x00s\x98\x01\xff\xf8\x00\x7f\x00\x07\xff\xff\xc0!\x00\x1f\xff\xfc\x00\x7f\x00\x03\xf1\xff\xf8\x00\x01\xff\xf1\xfc\x00\x7f\x00\x03\xf0?\xff\x00\x0f\xff\x81\xf8\x00\x7f\x00\x01\xe0\x07\xff\xf0\x07\xfc\x01\xf8\x00\x7f\x00\x00\x00\x00\xff\xfe\x00`\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xfc\x00\x00\x00\x00\x7f\x00\x00p\x01\xc0\x7f\xff\xc0\x00\x00\x00\x7f\x00\x00\xfc\x1f\xf8\x0f\xff\xf8\x03\xe0\x00\x7f\x00\x01\xfd\xff\xfe\x01\xff\xff\x87\xf0\x00\x7f\x00\x03\xff\xff\xfe\x00?\xff\xff\xf0\x00\x7f\x00\x03\xff\xff\xf0\x00\x07\xff\xff\xf0\x00\x7f\x00\x01\xff\xff\x80\x00\x00\xff\xff\xf0\x00\x7f\x00\x00\xff\xfc\x00\x00\x00\x1f\xff\xf0\x00\x7f\x00\x00?\xc0\x00\x00\x00\x03\xff\xe0\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x7f\x80\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Snow=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\r\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0c\xc0\x00\x02\x00\x7f\x00\x00\x00\x00\x00\x00\x13 \x00\x04\x00\x7f\x00\x00\x00\x00\x00\x00?\xf0\x00"`\x7f\x00\x10\x00\x00\x00\x00\x13`\x00\x1a\xc0\x7f\x00|\x00\x00\x00\x00\x04\x80\x00\x16\x00\x7f\x020\x80\x00\x01\x00\x0e\xc0\x00\x0f\x00\x7f\x02\xde\xc0\x00\x03\x00\x02\x80\x00\x1a\xc0\x7f\x0e\xba\xe0\x003\x18\x00\x00\x00$@\x7f\x07\xbb\xc0\x00;p\x00\x00\x00\x02\x00\x7f\t\xff0\x00\x1f\xe0\x00\x00\x00\x040\x7f\x03m\x80\x0c\x07\xc0@\x00\x00\x00x\x7f\x02\xee\xc0\x0c#\x10\xc0\x00\x00\x00p\x7f\r\xff\xb0\x0c{|\xc0\x00\x00\x00\x00\x7f\x07\xff\xc0l\xff\xfc\xcc\x00\x02\x00\x00\x7f\x0e\xba\xe0\xfc\xcf\xcc\xfc\x00\x1b`\x00\x7f\x02\xfe\x80<\xd3\xac\xf0\x00\x1f\xc0\x00\x7f\x02\x10\x80\x1f\xdbo\xf0\x00\x0f\xc0\x00\x7f\x00|\x00\x7f\xcf\xef\xfc\x08\x07\x00\x80\x7f\x00T\x00\xf1\xff\xff\x1e\x08\x03\x00\xc0\x7f\x00\x10\x00\x07\xff\xff\x80\x0c\x13 \x80\x7f\x00\x00\x00\x0f?\xf3\xe0<{y\xb0\x7f\x00\x00\x00\x1c\xfc\xfd\xe0<\x7f\xd9\xe0\x7f\x00\x00\x00\x0c\xfc~ ?g\x93\xe0\x7f\x00\x00\x00\x1e<\xf0\xe0\xff\xa77\xf8\x7f\x00\x80\x00\x07\xff\xfb\xc0\xe1\xe3>8\x7f\x00\x00\x00\xe3\xff\xff\x1e\x00\xfb|\x00\x7f\x02\xe0\x00\xff\xcf\xef\xbc\x03\xff\xff\x00\x7f\x01\x80\x00?\xdbo\xf0\x06\x0f\x83\x00\x7f\x00@\x00>\xd3,\xf8\x07\x9f\xc3\x00\x7f\x00\x80\x00|\xcf\xcc\xfc\x03\xff\xff\x00\x7f\x00\x00@\xec\xff\xfc\xce\x80\xf3<\x00\x7f\x00\x00\xc0\x0c\xfb|\xc0\xf9\xe3>x\x7f\x00\x00\xe0\x0c#\x10\xc0\x7f\'7\xf8\x7f\x00\x03\xf0\x0c\x07\xc0@>o\x91\xe0\x7f\x00\x03\xf0\x00\x1f\xe0\x00<{\xd9\xf0\x7f\x00\n\xd0\x00;\xf0\x00,{q\xa0\x7f\x00\x1e\xde\x0038\x00\x0c\x03\x00\xc0\x7f\x0e\x9c\xce|\x03\x00\x00\x08\x03\x00\xc0\x7f\x07\x87\xf8|\x01\x00\x00\x08\x07\x00\x80\x7f\x05\x8f\xdc|\x00\x00\x00\x00\x0f\xc0\x00\x7f\x03\xfe\xde\xf8\x00\x00\x00\x00\x1f\xe0\x00\x7f\x009\xf3\x10\x00\x00\x00\x00\x1b`\x00\x7f\x01\x9f\xff \x00\x00\x00\x00\x00\x00\x00\x7f\x00\xa7\xf9`\x00\x00\x00\x00\x10\x00\x00\x7f\x01\xff\xff\xe0\x00\x00\x00\x00\\\x00\x00\x7f\x01\xff\xff\xf0\x00\x00\x00\x008\x00\x00\x7f\x00\xa7\xfd`\x00\x00\x00\x02T\x80\x00\x7f\x01\x9d\xff \x00\x00\x00\x0e\xfe\xe0\x00\x7f\x033\xf3\x98\x00\x00\x00\x07\x9b\xc0\x00\x7f\x05\xde\xde\xe0\x00\x00\x00\r\xffp\x00\x7f\x07\x87\xd8|\x00\x02\x00\x03\x7f\x80\x00\x7f\x0f\xaf\xfd|\x00\x00\x00\x02\xee\xc0\x00\x7f\x02\x8c\xce0\x00\x12 \x03\xff\x80\x00\x7f\x00\x1e\xce\x00\x00\t\x80\r\xffp\x00\x7f\x00\x02\xc8\x00\x00\x07\x00\x07\xbb\xc0\x00\x7f\x00\x01\xf0\x00\x00\x0b\x80\x0e\xfe\xe0\x00\x7f\x00\x03\xd0\x00\x00\x19`\x02\xd4\x80\x00\x7f\x00\x01\xe0\x00\x00\x00\x00\x008\x80\x00\x7f\x00\x00\xe0\x00\x00\x03\x00\x00\\\x00\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x10\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Target=b"P4\n89 64\n\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xfb\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xf8\x08\x1f\xe0\x00\x00\x00\x7f\x00\x00\x00\x07\xe1\x00\x01\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x10\x84 \xfc\x00\x00\x00\x7f\x00\x00\x00<\x00B\x10\x1e\x00\x00\x00\x7f\x00\x00\x00x\x84!\x08O\x00\x00\x00\x7f\x00\x00\x00\xe0B\x10\x84\x03\x80\x00\x00\x7f\x00\x00\x01\xe4!\x08B\x13\xc0\x00\x00\x7f\x00\x00\x03\x82\x10\x84!\x01\xe0\x00\x00\x7f\x00\x00\x07\xa1\x08B\x10\x84\xf0\x00\x00\x7f\x00\x00\x0e\x10\x84 \x08@x\x00\x00\x7f\x00\x00\x0e\x08B\x0c\x84!8\x00\x00\x7f\x00\x00\x1c\x84 \x08B\x10\x1c\x00\x00\x7f\x00\x008B\x10\xff\x01\x08N\x00\x00\x7f\x00\x008!\x03\xff\xe0\x84\x0e\x00\x00\x7f\x00\x00r\x10\x8f\x89\xf8B\x17\x00\x00\x7f\x00\x00q\x08\x1eU\xaa\xf8\x83\xf0\x00\x7f\x00\x01\xc8\x0b\x15MUp@\xe0\x00\x7f\x00\x01\x84'j\xaa\x95d!\xc0\x00\x7f\x00\x01\xc2\x03\x95Ujb\x01\xc0\x00\x7f\x00\x01\xc1\x0b\xaa\xaa\x92\xe1\t\xc0\x00\x7f\x00\x01\xc0\x81\xaa\xb6n\xc0\x85\xc0\x00\x7f\x00\x01\xc8C\xd5I\x91\xc8A\xc0\x00\x7f\x00\x00\xe4 \xd56m\x84!\x80\x00\x7f\x00\x00\xe2\x10\xea\xc9\x93\x82\x13\x80\x00\x7f\x00\x00\xe1\x08u6w!\x03\x80\x00\x7f\x00\x00`\x849\xc9\x8e\x10\x87\x00\x00\x7f\x00\x00pB\x1e6<\x08G\x00\x00\x7f\x00\x00t!\x0f\x89\xf8\x84'\x00\x00\x7f\x00\x008\x10\x83\xff\xe0B\x0e\x00\x00\x7f\x00\x009\x08B\xff\x84!\x0e\x00\x00\x7f\x00\x00\x1c\x84 ,\x02\x10\x9c\x00\x00\x7f\x00\x00\x0eB\x10\x98!\x088\x00\x00\x7f\x00\x00\x0e\x01\x08B\x10\x848\x00\x00\x7f\x00\x00\x07\x90\x84!\x08Bp\x00\x00\x7f\x00\x00\x03\xc0B\x10\x84 \xe0\x00\x00\x7f\x00\x00\x01\xe4!\x08B\x13\xc0\x00\x00\x7f\x00\x00\x00\xe0\x10\x84!\x03\x80\x00\x00\x7f\x00\x00\x00y\x08B\x10\x8f\x00\x00\x00\x7f\x00\x00\x00<\x84!\x08\x1e\x00\x00\x00\x7f\x00\x00\x00\x1f\x02\x10\x84|\x00\x00\x00\x7f\x00\x00\x00\x07\xc1\x00A\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xf8\x08\x0f\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xeb\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" diff --git a/mixly/boards/default/micropython/build/lib/oled128x64.py b/mixly/boards/default/micropython/build/lib/oled128x64.py new file mode 100644 index 00000000..d47f3673 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/oled128x64.py @@ -0,0 +1,14 @@ +""" +OLED Displays + +Micropython library for the SSD1106_I2C OLED Displays +======================================================= +@dahanzimin From the Mixly Team +""" +from ssd1106 import SSD1106_I2C + +class OLED(SSD1106_I2C): + """A single matrix.""" + def __init__(self, i2c, width=128, height=64, address=0x3c, font_address=0x700000, types=0): + super().__init__(width, height, i2c, address, l_offset=0 if types == 0 else -2) + self.font(font_address) diff --git a/mixly/boards/default/micropython/build/lib/ollama.py b/mixly/boards/default/micropython/build/lib/ollama.py new file mode 100644 index 00000000..5ecd4a78 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ollama.py @@ -0,0 +1,111 @@ +import urequests +import time +import json + + +class Ollama(): + def __init__(self, url="", model="", max_history_num=0): + self._heads = { + "Accept": "text/event-stream", + # "Cache-Control": "no-cache", + # "Connection": "keep-alive", + "Content-Type": "application/json" + } + self._url = url + self._chat_url = "{}/api/chat".format(self._url) + self._max_retries = 1 + self._max_history_num = max_history_num + self._timeout = 10000 + self._messages = [] + self._data = { + "stream": True, + "model": model, + "messages": self._messages + } + + def set_timeout(self, timeout): + self._timeout = timeout + + def set_max_retries(self, max_retries): + self._max_retries = max_retries + + def set_custom_url(self, url): + self._url = url + self._chat_url = "{}/api/chat".format(self._url) + + def select_model(self, model_name): + self._data["model"] = model_name + + def set_max_history_num(self, num): + self._max_history_num = num + + def empty_history(self): + self._messages = [] + + def add_history(self, role, content): + self._messages.append({ + "role": role, + "content": content + }) + + def clear_user_history(self): + if len(self._messages) < 2: + return + for i in range(1, len(self._messages)): + del self._messages[i] + + def _post(self, content_callback=None): + response = None + data = json.dumps(self._data).encode('utf-8') + for i in range(0, self._max_retries): + response = urequests.post( + self._chat_url, headers=self._heads, data=data) + if response.status_code == 200: + break + time.sleep(1) + + output = "" + + if response.status_code != 200: + output = response.text + if content_callback: + content_callback(output) + return output + + if not content_callback: + output = json.loads(response.text)["message"]["content"] + response.close() + return output + + try: + while True: + line = response.raw.readline() + if line: + line = line.decode('utf-8').strip() + data = json.loads(line) + if data["done"]: + break + content = data["message"]["content"] + content_callback(content) + output += content + else: + break + finally: + response.close() + return output + + def chat(self, message, content_callback=None): + self.add_history("user", message) + self._data["stream"] = bool(content_callback) + self._heads["Accept"] = "text/event-stream" if content_callback else "application/json" + content = self._post(content_callback) + if self._max_history_num: + self.add_history("assistant", content) + messages_len = len(self._messages) + history_num = 2 * self._max_history_num + while history_num < messages_len: + del self._messages[0] + else: + self.clear_user_history() + + return content diff --git a/mixly/boards/default/micropython/build/lib/onenet.py b/mixly/boards/default/micropython/build/lib/onenet.py new file mode 100644 index 00000000..109fc1cb --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/onenet.py @@ -0,0 +1,34 @@ +import ujson as json +from umqtt import MQTTClient,str_len + +def get_data_dict(d): + result = {"datastreams":[]} + for x in d: + result["datastreams"].append({"id":x,"datapoints":[{"value":d[x]}]}) + return result + +def pubData(value, state): + value = get_data_dict(value) + jdata = json.dumps(value) + jlen = str_len(jdata) + bdata = bytearray(jlen+3) + bdata[0] = 1 #publish data in type of json + bdata[1] = int(jlen / 256) # data lenght + bdata[2] = jlen % 256 # data lenght + bdata[3:jlen+4] = jdata.encode('ascii') # json data + if state: + print(value) + #print(bdata) + return bdata + +def init_MQTT_client(sid, address, cid, api, topic, callback): + client = MQTT_Client(sid, address, 6002, cid, api) + client.set_callback(callback) + client.connect() + client.subscribe(bytes(topic, 'utf-8')) + return client + +#inherit +class MQTT_Client(MQTTClient): + def publish(self, msg, is_print=False, topic='$dp', retain=False, qos=0): + super().publish('$dp',pubData(msg, is_print)) diff --git a/mixly/boards/default/micropython/build/lib/openai.py b/mixly/boards/default/micropython/build/lib/openai.py new file mode 100644 index 00000000..b4808ffb --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/openai.py @@ -0,0 +1,53 @@ +import urequests +import time +import json +import ollama + + +class OpenAI(ollama.Ollama): + def __init__(self, url="", api_key="", model="", max_history_num=0, max_tokens=1024): + super().__init__(url, model, max_history_num) + self._heads["Authorization"] = "Bearer {}".format(api_key) + self._data["max_tokens"] = max_tokens + self._chat_url = "{}/chat/completions".format(self._url) + + def _post(self, content_callback=None): + response = None + data = json.dumps(self._data).encode('utf-8') + for i in range(0, self._max_retries): + response = urequests.post( + self._chat_url, headers=self._heads, data=data) + if response.status_code == 200: + break + time.sleep(1) + + output = "" + + if response.status_code != 200: + output = response.text + if content_callback: + content_callback(output) + return output + + if not content_callback: + output = json.loads(response.text)[ + "choices"][0]["message"]["content"] + response.close() + return output + + try: + while True: + line = response.raw.readline() + if line[:5] != b"data:": + continue + if line[-7:-1] == b"[DONE]": + break + line = line[6:-1] + line = line.decode('utf-8').strip() + data = json.loads(line) + content = data["choices"][0]["delta"]["content"] + content_callback(content) + output += content + finally: + response.close() + return output diff --git a/mixly/boards/default/micropython/build/lib/pe_g1.py b/mixly/boards/default/micropython/build/lib/pe_g1.py new file mode 100644 index 00000000..ffba026a --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/pe_g1.py @@ -0,0 +1,126 @@ +""" +Micropython library for +PE_G1 (Motor*5*2 & Servo*4) +MDB (Motor*4*2 & Servo*6) +=============================== +@dahanzimin From the Mixly Team +""" +from time import sleep_ms +from micropython import const + +_PE_GX_ADDRESS = const(0x25) +_PE_GX_ID = const(0x00) +_PE_GX_VBAT = const(0x01) +_PE_GX_MOTOR = const(0x03) + +class PE_G1: + def __init__(self, i2c_bus, addr=_PE_GX_ADDRESS): + self._i2c = i2c_bus + self._addr = addr + sleep_ms(500) + if self._rreg(_PE_GX_ID) == 0x25: + self._PE_GX_SERVO = 0x0D + self._type = 1 #PE_G1 + elif self._rreg(_PE_GX_ID) == 0x26: + self._PE_GX_SERVO = 0x0B + self._type = 2 #MDB + else: + raise AttributeError("Cannot find a PE_G1 or MDB") + self.reset() + + def _wreg(self, reg, val): + '''Write memory address''' + try: + self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little')) + except: + return 0 + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + try: + self._i2c.writeto(self._addr, reg.to_bytes(1, 'little')) + return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes <= 1 else self._i2c.readfrom(self._addr, nbytes) + except: + return 0 + + def reset(self): + """Reset all registers to default state""" + if self._type == 1: + self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(18)) + if self._type == 2: + self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(20)) + + def read_bat(self, ratio=1): + '''Read battery power''' + vbat = self._rreg(_PE_GX_VBAT) << 2 | self._rreg(_PE_GX_VBAT+1) >> 6 + if self._type == 1: + return round(vbat * ratio * 0.00968, 2) + if self._type == 2: + return round(vbat * ratio * 0.01398, 2) + + def m_pwm(self, index, duty=None): + """Motor PWM duty cycle data register""" + if self._type == 1: # Motor*5*2 + if not 0 <= index <= 9: + raise ValueError("Motor port must be a number in the range: 0~4") + if self._type == 2: # Motor*4*2 + if not 0 <= index <= 7: + raise ValueError("Motor port must be a number in the range: 0~3") + if duty is None: + return self._rreg(_PE_GX_MOTOR + index) + else: + if not 0 <= duty <= 255: + raise ValueError("Duty must be a number in the range: 0~255") + self._wreg(_PE_GX_MOTOR + index, duty) + + def s_pwm(self, index, duty=None): + """Servo PWM duty cycle data register""" + if self._type == 1: # Servo*4 + if not 0 <= index <= 3: + raise ValueError("Servo port must be a number in the range: 0~3") + if self._type == 2: # Servo*6 + if not 0 <= index <= 5: + raise ValueError("Servo port must be a number in the range: 0~5") + if duty is None: + return self._rreg(self._PE_GX_SERVO + index * 2) << 8 | self._rreg(self._PE_GX_SERVO + index * 2 + 1) + else: + if not 0 <= duty <= 4095: + raise ValueError("Duty must be a number in the range: 0~4095") + self._wreg(self._PE_GX_SERVO + index * 2,duty >> 8) + self._wreg(self._PE_GX_SERVO + index * 2 + 1,duty & 0xff) + + def motor(self, index, action="NC", speed=0): + if not 0 <= speed <= 100: + raise ValueError("Speed parameters must be a number in the range: 0~100") + if action == "N": + self.m_pwm(index * 2, 0) + self.m_pwm(index * 2 + 1, 0) + elif action == "P": + self.m_pwm(index * 2, 255) + self.m_pwm(index * 2 + 1, 255) + elif action == "CW": + self.m_pwm(index * 2, 0) + self.m_pwm(index * 2 + 1, speed * 255 // 100) + elif action == "CCW": + self.m_pwm(index * 2, speed * 255 // 100) + self.m_pwm(index * 2 + 1, 0) + elif action == "NC": + return round(self.m_pwm(index * 2) * 100 / 255), round(self.m_pwm(index * 2 + 1) * 100 / 255) + else: + raise ValueError('Invalid input, valid are "N","P","CW","CCW"') + + def servo180(self, index, angle=None): + if angle is None: + return round((self.s_pwm(index) - 102.375) * 180 / 409.5) + else: + if not 0 <= angle <= 180: + raise ValueError("Servo(180) angle must be a number in the range: 0~180") + self.s_pwm(index,round(102.375 + 409.5 / 180 * angle)) + + def servo360(self, index, speed=None): + if speed is None: + return round((self.s_pwm(index) - 102.375) * 200 / 409.5 - 100) + else: + if not -100 <= speed <= 100: + raise ValueError("Servo(360) speed must be a number in the range: -100~100") + self.s_pwm(index,round(102.375 + 409.5 / 200 * (speed + 100))) diff --git a/mixly/boards/default/micropython/build/lib/pm2_5.py b/mixly/boards/default/micropython/build/lib/pm2_5.py new file mode 100644 index 00000000..d7989822 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/pm2_5.py @@ -0,0 +1,41 @@ +""" +PM2.5 + +Micropython library for the PM2.5(UART) +======================================================= +#Preliminary composition 20220908 + +dahanzimin From the Mixly Team +""" +import time + +class PM2_5: + def __init__(self, uart): + self._uart=uart + self._uart.init(baudrate=9600) + self._pm=(0,0) + self._flag=False + if not self._chip_id(): + raise AttributeError("Cannot find a PM2.5") + + def _rreg(self): + '''Read data''' + if self._uart.any(): + eec=0 + buf=self._uart.read(7) + for i in buf[1:5]: + eec+=i + if (eec & 0xff) == buf[5] and buf[0] == 0xAA and buf[6] == 0xFF: + self._pm=(buf[1] << 8 | buf[2] , buf[3] << 8 | buf[4] ) + return True + + def _chip_id(self): + for _ in range(5): + if self._rreg(): + return True + time.sleep(1) + return False + + def concentration(self): + self._rreg() + return self._pm diff --git a/mixly/boards/default/micropython/build/lib/progres_picture.py b/mixly/boards/default/micropython/build/lib/progres_picture.py new file mode 100644 index 00000000..5304dc14 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/progres_picture.py @@ -0,0 +1,29 @@ +#Take the picture bytes in progres_picture.py +#--dahanzimin From the Mixly Team + +Bar_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1ca\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x16\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x002w@\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\x1ea\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05\x90\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x9c\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x86w@\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x02\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xbe\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xaa\xaa\xaa\xc0\x00\x00\x00\x00\x00\x00\xff\xd5RIU\x80\x00\x00\x00\x00\x00\x00\xff\xea\xad\xb6\xab\x00\x00\x00\x00\x00\x00\x00\xff\xd5RIV\x00\x00\x00\x00\x00\x00\x00\xff\xea\xad\xb6\xac\x00\x00\x00\x00\x00\x00\x00\xff\xd5RIX\x00\x00\x00\x00\x00\x00\x00\xff\xd5m\xb6\xb0\x00\x00\x00\x00\x00\x00\x00\xff\xea\x92I`\x00\x00\x00\x00\x00\x00\x00\xff\xd5m\xb6\xc0\x00\x00\x00\x00\x00\x00\x00\xff\xca\x92I\x80\x00\x00\x00\x00\x00\x00\x00\xff\xfbm\xb7\x00\x00\x00\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\x9ca\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x04\x16\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x072\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xb2w@\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xb2\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x9e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xaa\xaa\xaa\xaa\xaa\xac\x00\x00\x00\x00\xff\xd5$\x92I$\x95X\x00\x00\x00\x00\xff\xea\xdbm\xb6\xdbj\xb0\x00\x00\x00\x00\xff\xd5$\x92I$\x95`\x00\x00\x00\x00\xff\xd6\xdbm\xb6\xdbj\xc0\x00\x00\x00\x00\xff\xe9$\x92I$\x95\x80\x00\x00\x00\x00\xff\xd6\xdbm\xb6\xdbk\x00\x00\x00\x00\x00\xff\xc9$\x92I$\x96\x00\x00\x00\x00\x00\xff\xf6\xdbm\xb6\xdbl\x00\x00\x00\x00\x00\xff\xc9$\x92I$\x98\x00\x00\x00\x00\x00\xff\xf6\xdbm\xb6\xdbp\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x9ea\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x90\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x9c\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x06w@\x00\x00\x00\x7f\x00\x00\x00\x00\x02\x02\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x06>\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd5UUUUUUUU\x80\x00\xff\xd5RI$\x92I$\x92\xab\x00\x00\xff\xea\xad\xb6\xdbm\xb6\xdbmV\x00\x00\xff\xd5RI$\x92I$\x92\xac\x00\x00\xff\xea\xad\xb6\xdbm\xb6\xdbmX\x00\x00\xff\xd5RI$\x92I$\x92\xb0\x00\x00\xff\xd5m\xb6\xdbm\xb6\xdbm`\x00\x00\xff\xea\x92I$\x92I$\x92\xc0\x00\x00\xff\xd5m\xb6\xdbm\xb6\xdbm\x80\x00\x00\xff\xca\x92I$\x92I$\x93\x00\x00\x00\xff\xfbm\xb6\xdbm\xb6\xdbn\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_4=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x87\x1ca\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xc5\x96\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2w@\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2\x0b@\x00\x00\x00\x7f\x00\x00\x00\x01\xe7\x9e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd5UUUUUUUUUU\xff\xd5$\x92I$\x92I$\x92I*\xff\xea\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xd5$\x92I$\x92I$\x92I+\xff\xd6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xe9$\x92I$\x92I$\x92I+\xff\xd6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xc9$\x92I$\x92I$\x92I+\xff\xf6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xc9$\x92I$\x92I$\x92I%\xff\xf6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xdb\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x0c\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00w@\x00\x00\x02\xc0\x7f\x00\x80\x00?\xff\xf9\x00\x00\x00\x00@\x7f\x07\xe1\x7f\xff\xff\xfd\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\xff\xff\xff\xfc\x80\x00\x00\x03\xf8\x7f\x00\x00\x00?\xff\xfd\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xfb\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x88\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x02\x80\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x83\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x01\x80\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\xc0\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00`\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x010\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x1c\x80\x00\x00\x00\x00\x17\x00\x7f\x00t\x00N@\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x0f \x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x17\x80\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x03\xc0\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x05\xf0\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\xf8\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00|\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00>@\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x1f\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x0f\xd0\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x0f\xe0\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x07\xf1\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x13\xfc\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x01\xff@\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x04\xf9\x00\x00\x00\x00@\x7f\x07\xe4\x00\x00\x02}\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xfc\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x02\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x08\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00$\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x0c\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x0c\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x0c\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x0c\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x0c\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x0c\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x0c\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x0c\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x0c\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x0c\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00N\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x1e\x80\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x1e\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x1e\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x1e\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x1e\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x1e\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00?\x00\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01\x7f\x00\x00\x00\x00@\x7f\x07\xe4\x00\x00\x00\x7f\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xde\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x0b`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x10\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00 \x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x02H\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\xd0\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x03\x80\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x07\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00N\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x1c\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x008\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\xf0\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\t\xe4\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x03\xc0\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x07\xd0\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x1f\x80\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00?\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00~\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x04\xfc\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\xf8\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x03\xf2\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x0f\xe0\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00?\xc0\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01o\xd0\x00\x00\x00@\x7f\x07\xe4\x00\x00\x00O\x80\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xcf\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00a\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_4=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x1c\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x007\x00\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01o\xff\xf0\x00\x00@\x7f\x07\xe4\x00\x00\x00O\xff\xff\xff\xab\xf8\x7f\x0f\xf0\x00\x00\x00\xcf\xff\xff\xff\x83\xf8\x7f\x00\x00\x00\x00\x00O\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" +Dots_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00 \x01\x02\x00\x10 \x01\x00\x00\x7f\x00\x00\x10\x02\x01\x00 \x10\x02\x00\x00\x7f\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x0f\xc0\x00\x80\x00\x7f\x00\x00@\x00\xfc\x00\x0f\xc0\x00\x00\x00\x7f\x00\x00@\x00\x84\x00\x08@\x00\x80\x00\x7f\x00\x00\x00\x02\x00\x00 \x00\x02\x00\x00\x7f\x00\x00(\x01\x02\x80\x10(\x01\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x80\x00\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dots_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x03\xf0\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x07\xf8\x00@\x80\x04\x08\x00\x00\x7f\x00\x00/\xfd\x02\x00\x10 \x01\x00\x00\x7f\x00\x00\x1f\xfe\x01\x00 \x10\x02\x00\x00\x7f\x00\x00\x1f\xfe\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00_\xfe\xfc\x00\x0f\xc0\x00\x80\x00\x7f\x00\x00\x1f\xfe\xfc\x00\x0f\xc0\x00\x00\x00\x7f\x00\x00_\xfe\x84\x00\x08@\x00\x80\x00\x7f\x00\x00\x1f\xfe\x00\x00 \x00\x02\x00\x00\x7f\x00\x00/\xfd\x02\x80\x10(\x01\x00\x00\x7f\x00\x00\x07\xf8\x00\x00\x80\x00\x08\x00\x00\x7f\x00\x00\x03\xf0\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dots_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00?\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00\x7f\x80\x04\x08\x00\x00\x7f\x00\x00 \x01\x02\xff\xd0 \x01\x00\x00\x7f\x00\x00\x10\x02\x01\xff\xe0\x10\x02\x00\x00\x7f\x00\x00@\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfd\xff\xef\xc0\x00\x80\x00\x7f\x00\x00@\x00\xfd\xff\xef\xc0\x00\x00\x00\x7f\x00\x00@\x00\x85\xff\xe8@\x00\x80\x00\x7f\x00\x00\x00\x02\x01\xff\xe0\x00\x02\x00\x00\x7f\x00\x00(\x01\x02\xff\xd0(\x01\x00\x00\x7f\x00\x00\x00\x08\x00\x7f\x80\x00\x08\x00\x00\x7f\x00\x00\x02\x10\x00?\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dots_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x03\xf0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x07\xf8\x00\x00\x7f\x00\x00 \x01\x02\x00\x10/\xfd\x00\x00\x7f\x00\x00\x10\x02\x01\x00 \x1f\xfe\x00\x00\x7f\x00\x00@\x00\x00\x00\x00\x1f\xfe\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x0f\xdf\xfe\x80\x00\x7f\x00\x00@\x00\xfc\x00\x0f\xdf\xfe\x00\x00\x7f\x00\x00@\x00\x84\x00\x08_\xfe\x80\x00\x7f\x00\x00\x00\x02\x00\x00 \x1f\xfe\x00\x00\x7f\x00\x00(\x01\x02\x80\x10/\xfd\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x80\x07\xf8\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x03\xf0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hourglass_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf0\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06UUUP\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x02UUU0\x00\x00\x00\x7f\x00\x00\x00\x03UUU \x00\x00\x00\x7f\x00\x00\x00\x01\xaa\xaa\xaa`\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UT\xc0\x00\x00\x00\x7f\x00\x00\x00\x00j\xaa\xa9\x80\x00\x00\x00\x7f\x00\x00\x00\x005US\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xa6\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rUL\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x98\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xaa`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xd4\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00i\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc1\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x88\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x080\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0c\x00\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x08\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x08\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x08\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x00\x00`\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x08\x000\x00\x00\x00\x7f\x00\x00\x00\x02\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x06\x00\n\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00*\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00U@\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x01U@\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x02\xaa\xa8\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x05UT\x10\x00\x00\x00\x7f\x00\x00\x00\x06]\xb6\xdb\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf8\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hourglass_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf0\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x02\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x00\x00 \x00\x00\x00\x7f\x00\x00\x00\x01\x80\x00\x00`\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00`*\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x002\xaa\x83\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xa6\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rUL\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x98\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xaa`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xd4\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00i\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc9\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x08`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x000\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0c\x08\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x08\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x08\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x14\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\x00U\x00`\x00\x00\x00\x7f\x00\x00\x00\x03\x00\xaa\x800\x00\x00\x00\x7f\x00\x00\x00\x02\x05U@0\x00\x00\x00\x7f\x00\x00\x00\x06\x15UT\x10\x00\x00\x00\x7f\x00\x00\x00\x06UUU\x10\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06UUUP\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xdbm\xb6\xd0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf8\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hourglass_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\x90\x00\x00\x00\x00\x00\x05\x80\x00\x7f\x00\x00\x9f\xfc\x00\x00\x00\x1f\xfc\x80\x00\x7f\x00\x00\x9f\xff\x80\x00\x00\x7f\xfc\x80\x00\x7f\x00\x00\x94\x01\xc0\x00\x00\xc0\x14\x80\x00\x7f\x00\x00\x9c\x00`\x00\x01\x80\x1c\x80\x00\x7f\x00\x00\x94\x000\x00\x03\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x18\x00\x06\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x0c\x00\x0c\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x06\x00\x18\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x03\x000\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x01\x80`\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x00\xc0\xc0\x00\x14\x80\x00\x7f\x00\x00\x9d\x00\x00a\x80\x00\x1c\x80\x00\x7f\x00\x00\x95@\x003\x00\x00\x14\x80\x00\x7f\x00\x00\x9dP\x00\x1e\x00\x00\x1c\x80\x00\x7f\x00\x00\x94\xb4\x00\x0c\x00\x00\x14\x80\x00\x7f\x00\x00\xbdJ@\x00\x00\x00\x1d\x80\x00\x7f\x00\x00\xf4\xb5\xa9\x00\x00\x00\x15\x80\x00\x7f\x00\x00\xfdJU\\\x00\x00\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xaa\xb6\x00\x00\x17\x80\x00\x7f\x00\x00\xfdJUc\x00\x00\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xaa\xc1\x85\x00\x17\x80\x00\x7f\x00\x00\xfdJU\x80\xca\xc0\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xab\x00e*W\x80\x00\x7f\x00\x00\xfdJV\x002\xda\x9f\x80\x00\x7f\x00\x00\xf4\xb5\xac\x00\x19%W\x80\x00\x7f\x00\x00\xfdJX\x00\x0c\xda\x9f\x80\x00\x7f\x00\x00\xf5u\xb0\x00\x06%W\x80\x00\x7f\x00\x00\xfd\n`\x00\x039_\x80\x00\x7f\x00\x00\xf5\xf8\xc0\x00\x01\x87W\x80\x00\x7f\x00\x00\xfc\x03\x80\x00\x00\xf0_\x80\x00\x7f\x00\x00\xff\xff\x00\x00\x00?\xff\x80\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x0f\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80/\x00|p\x00\x00\x7f\x00\x00\x01\xbe\x00!\x00>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!\x00\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00#\x00\x07\x80\x00\x00\x7f\x00\x00\x01\xe0\x00.\x00\x03\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(\x00\x01\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(\x00\x00\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/\x00\x00p\x00\x00\x7f\x00\x00\x07\x00\x00\x00\x00\x00x\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x00y\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x00q \x00\x00\x00\x00G\x00\x00\x7f\x00\x00q \x00\x00\x00\x00G\x00\x00\x7f\x00\x00q\xe0\x00\x00\x00\x01\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00G\x00\x00\x7f\x00\x00x \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x009\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x07\x80\x00\x1e\x00\x00x\x00\x00\x7f\x00\x00\x03\x80\x00\x10\x00\x00\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1e\x00\x03\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\x00\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\x00>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00\x00\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!U\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!*\x87\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/U\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(*Q\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(U\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/*Tp\x00\x00\x7f\x00\x00\x07\x00\x00\x00U\xa8x\x00\x00\x7f\x00\x00\x0f\x00\x00\x00RV8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05m\xa9<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\x92V\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05m\xa9\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\n\x92V\x8e\x00\x00\x7f\x00\x008\x00\x00\x05m\xa8\x8e\x00\x00\x7f\x00\x008\x00\x00\n\x92W\xcf\x00\x00\x7f\x00\x008\x00\x00\x05m\xa8\x0f\x00\x00\x7f\x00\x008\x00\x00\n\x92P\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05m\xb3\xc7\x00\x00\x7f\x00\x00q \x00\n\x92HG\x00\x00\x7f\x00\x00q \x00\x05m\xb4G\x00\x00\x7f\x00\x00q\xe0\x00\x04\x92I\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00G\x00\x00\x7f\x00\x00x \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x009\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x07\x80\x00\x1e\x00\x00x\x00\x00\x7f\x00\x00\x03\x80\x00\x10\x00\x00\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1e\x00\x03\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\x00\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\x00>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00\x00\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!UG\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/UTp\x00\x00\x7f\x00\x00\x07\x00\x00\x00UTx\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UU\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UV\x8e\x00\x00\x7f\x00\x008\x00\x00\x05UP\x8e\x00\x00\x7f\x00\x008\x00\x00\n\xaa\xaf\xcf\x00\x00\x7f\x00\x008\x00\x00\x05UP\x0f\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x00q \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00q \x00\x05UTG\x00\x00\x7f\x00\x00q\xe0\x00\n\xaa\xa9\xc7\x00\x00\x7f\x00\x00p \x00\x05UT\xc7\x00\x00\x7f\x00\x00p \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00x \x00\x05UP\xc7\x00\x00\x7f\x00\x009\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x008\x00\x00\x05UUO\x00\x00\x7f\x00\x008\x00\x00\x05UUN\x00\x00\x7f\x00\x00<\x00\x00\n\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UUN\x00\x00\x7f\x00\x00\x1c\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1e\x00\x00\x05UU\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x80\x00\x1eUTx\x00\x00\x7f\x00\x00\x03\x80\x00\x10\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x11J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!UG\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/UTp\x00\x00\x7f\x00\x00\x07\x00\x00\x00UTx\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UU\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UV\x8e\x00\x00\x7f\x00\x008\x00\x00\x05UP\x8e\x00\x00\x7f\x00\x008\x00\x00\n\xaa\xaf\xcf\x00\x00\x7f\x00\x008\x00\x00\x05UP\x0f\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x00q \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00q \x00\x05UTG\x00\x00\x7f\x00\x00q\xe0\x00\n\xaa\xa9\xc7\x00\x00\x7f\x00\x00p%UUUT\xc7\x00\x00\x7f\x00\x00p"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00x%UUUP\xc7\x00\x00\x7f\x00\x009\xe5UUUS\xc7\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x07\x00\x00\x7f\x00\x008\xd5UUUUO\x00\x00\x7f\x00\x008UUUUUN\x00\x00\x7f\x00\x00<\xaa\xaa\xaa\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1cUUUUUN\x00\x00\x7f\x00\x00\x1cUUUUU\x9c\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x1c\x00\x00\x7f\x00\x00\x0e\x15UUUU<\x00\x00\x7f\x00\x00\x0f\x15U@\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x8a\xaa\x9eUTx\x00\x00\x7f\x00\x00\x03\x8a\xaa\x90\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc2\xaa\x91J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe2\xaa\x90\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\xaa\x9eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x*\x92\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<*\x92J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x05\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x80@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_4=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x81.@|p\x00\x00\x7f\x00\x00\x01\xbe\x15#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc*!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0U!UG\x80\x00\x00\x7f\x00\x00\x01\xe1U/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc1U(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc5U(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x85U/UTp\x00\x00\x7f\x00\x00\x07\x15U\x00UTx\x00\x00\x7f\x00\x00\x0f\n\xaa\x80\xaa\xaa8\x00\x00\x7f\x00\x00\x0e*\xaa\xaa\xaa\xaa<\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1cUUUUU\x1e\x00\x00\x7f\x00\x00\x1cUUUUU\x8e\x00\x00\x7f\x00\x008\x15UUUTN\x00\x00\x7f\x00\x008\xf5UUUW\xcf\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x0f\x00\x00\x7f\x00\x008\x05UUUP\x07\x00\x00\x7f\x00\x00y\xe5UUUS\xc7\x00\x00\x7f\x00\x00q"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00q%UUUTG\x00\x00\x7f\x00\x00q\xe2\xaa\xaa\xaa\xa9\xc7\x00\x00\x7f\x00\x00p%UUUT\xc7\x00\x00\x7f\x00\x00p"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00x%UUUP\xc7\x00\x00\x7f\x00\x009\xe5UUUS\xc7\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x07\x00\x00\x7f\x00\x008\xd5UUUUO\x00\x00\x7f\x00\x008UUUUUN\x00\x00\x7f\x00\x00<\xaa\xaa\xaa\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1cUUUUUN\x00\x00\x7f\x00\x00\x1cUUUUU\x9c\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x1c\x00\x00\x7f\x00\x00\x0e\x15UUUU<\x00\x00\x7f\x00\x00\x0f\x15U@\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x8a\xaa\x9eUTx\x00\x00\x7f\x00\x00\x03\x8a\xaa\x90\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc2\xaa\x91J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe2\xaa\x90\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\xaa\x9eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x*\x92\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<*\x92J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x05\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x80@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Water_level_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff>?\xcf\xff\xff\xff\xff\xfd\xff\xff\xbf\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Water_level_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff>?\xcf\xff\xff\xff\xff\xfd\xff\xff\xbf\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Water_level_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff\x1e?\xcf\xff\xff\xff\xff\xfd\xff\xff?\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Water_level_3=b'P4\n89 64\n\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff\x1e?\xcf\xff\xff\xff\xff\xfd\xff\xff?\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe1\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xbf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8o\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0O\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xe0\x1f\xff\xff\xff\xff\x17\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\x07\xff\xff\xff\xff\xff\xfco\xff\xff\xff\xff\x07\xff\xff\xff\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' diff --git a/mixly/boards/default/micropython/build/lib/ps2.py b/mixly/boards/default/micropython/build/lib/ps2.py new file mode 100644 index 00000000..298263e6 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ps2.py @@ -0,0 +1,115 @@ +""" +PS2Controller + +MicroPython library for the PS2Controller +======================================================= + +#Perform upgrade repair 20220819 + +dahanzimin From the Mixly Team +""" + +import time +from machine import Pin +from micropython import const + +PSB_SELECT = const(0x0001) +PSB_L3 = const(0x0002) +PSB_R3 = const(0x0004) +PSB_START = const(0x0008) +PSB_PAD_UP = const(0x0010) +PSB_PAD_RIGHT = const(0x0020) +PSB_PAD_DOWN = const(0x0040) +PSB_PAD_LEFT = const(0x0080) +PSB_L2 = const(0x0100) +PSB_R2 = const(0x0200) +PSB_L1 = const(0x0400) +PSB_R1 = const(0x0800) +PSB_GREEN = const(0x1000) +PSB_RED = const(0x2000) +PSB_BLUE = const(0x4000) +PSB_PINK = const(0x8000) +PSB_TRIANGLE = const(0x1000) +PSB_CIRCLE = const(0x2000) +PSB_CROSS = const(0x4000) +PSB_SQUARE = const(0x8000) + +PSS_RX = const(0) +PSS_RY = const(1) +PSS_LX = const(2) +PSS_LY = const(3) + +class PS2Controller: + def __init__(self,clk_pin,do_pin,di_pin,cs_pin,mode=1,timeout=1000): #mode: 0 red; 1 green + self.di =Pin(di_pin,Pin.IN) + self.do =Pin(do_pin,Pin.OUT) + self.cs =Pin(cs_pin,Pin.OUT) + self.clk=Pin(clk_pin,Pin.OUT) + + self.buttons=0 + self.last_buttons=0 + self.rods=(128,128,128,128) + self.motor1=0 + self.motor2=0 + + timestamp = time.ticks_ms() + while not (self._cmds([0x01,0x42])[1] in [0x41,0x73,0x79,0xF3]): + if time.ticks_diff(time.ticks_ms(), timestamp) > timeout: + raise AttributeError("Cannot find a PS2Controller",self._cmds([0x01,0x42])[1]) + + self._cmds([0x01,0x43,0x00,0x01,0x00]) # 进入配置模式 + time.sleep_ms(10) + self._cmds([0x01,0x44,0x00,mode,0x03,0x00,0x00,0x00,0x00]) # “红绿灯”配置模式 + time.sleep_ms(10) + self._cmds([0x01,0x4D,0x00,0x00,0x01]) # 开启震动模式 + time.sleep_ms(10) + self._cmds([0x01,0x43,0x00,0x00,0x5A,0x5A,0x5A,0x5A,0x5A]) # 完成并保存配置 + time.sleep_ms(10) + + def _cmd(self,cmd): + '''Single byte command sending and receiving''' + ret = 0 + for i in range(8): + if cmd & 1 << i: + self.do.value(1) + else: + self.do.value(0) + self.clk.value(0) + time.sleep_us(10) + if self.di.value(): + ret |= 1 << i + self.clk.value(1) + self.do.value(1) + time.sleep_us(10) + return ret + + def _cmds(self,cmds): + '''Multi byte command sending and receiving''' + self.cs.value(0) + buffer=bytearray(9) + for i, cmd in enumerate(cmds): + buffer[i]=self._cmd(cmd) + self.cs.value(1) + time.sleep_ms(10) + return buffer + + def keydata(self): + """Read the value of the key""" + _buffer=self._cmds([0X01, 0X42, 0X00, self.motor1, self.motor2, 0X00, 0X00, 0X00, 0X00]) + if _buffer[2]==0x5A: + handkey=(_buffer[4]<<8)| _buffer[3] + self.buttons=-handkey-1 & 0xffff + self.rods=(_buffer[5],_buffer[6],_buffer[7],_buffer[8]) + return self.buttons,self.rods + + def vibration(self,motor1=0,motor2=0): + """Vibration settings""" + self.motor1=motor1 #motor1:小电机,只有震和不振 + self.motor2=0 if motor2<1 else motor2*0xBF//100+0X40 #motor2:大电机,范围0x40-0xff,映射0-100 + self._cmds([0X01, 0X42, 0X00, self.motor1, self.motor2, 0X00, 0X00, 0X00, 0X00]) + + def button(self,psb): + return (self.keydata()[0] & psb) > 0 + + def analog(self,pss): + return self.keydata()[1][pss] diff --git a/mixly/boards/default/micropython/build/lib/qmc5883l.py b/mixly/boards/default/micropython/build/lib/qmc5883l.py new file mode 100644 index 00000000..678ee7fc --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/qmc5883l.py @@ -0,0 +1,215 @@ +""" +QMC5883L + +MicroPython library for the QMC5883L 3-Axis Magnetic Sensor +======================================================= +#Preliminary composition 20220217 + +by https://github.com/RigacciOrg/py-qmc5883l.git + +dahanzimin From the Mixly Team +""" + +import math +import time +from micropython import const + +I2CADDR_DEFAULT = const(0x0D) # Default I2C address + +REG_XOUT_LSB = const(0x00) # Output Data Registers for magnetic sensor. +REG_YOUT_LSB = const(0x02) # Output Data Registers for magnetic sensor. +REG_ZOUT_LSB = const(0x04) # Output Data Registers for magnetic sensor. +REG_STATUS_1 = const(0x06) # Status Register. +REG_TOUT_LSB = const(0x07) # Output Data Registers for temperature. + +REG_CONTROL_1 = const(0x09) # Reg to control mode of compass. +REG_CONTROL_2 = const(0x0A) # Reg to contro2 mode of compass. +REG_RST_PERIOD = const(0x0B) # SET/RESET Period Register. +REG_CHIP_ID = const(0x0D) # Chip ID register. + +# Flags for Status Register #1. +STAT_DRDY = const(0b00000001) # Data Ready. +STAT_OVL = const(0b00000010) # Overflow flag. +STAT_DOR = const(0b00000100) # Data skipped for reading. +# Flags for Status Register #2. +INT_ENB = const(0b00000001) # Interrupt Pin Enabling. +SOFT_RST = const(0b10000000) # Soft Reset. +# Flags for Control Register 1. +MODE_STBY = const(0b00000000) # Standby mode. +MODE_CONT = const(0b00000001) # Continuous read mode. +ODR_10HZ = const(0b00000000) # Output Data Rate Hz. +ODR_50HZ = const(0b00000100) +ODR_100HZ = const(0b00001000) +ODR_200HZ = const(0b00001100) +RNG_2G = const(0b00000000) # Range 2 Gauss: for magnetic-clean environments. +RNG_8G = const(0b00010000) # Range 8 Gauss: for strong magnetic fields. +OSR_512 = const(0b00000000) # Over Sample Rate 512: less noise, more power. +OSR_256 = const(0b01000000) +OSR_128 = const(0b10000000) +OSR_64 = const(0b11000000) + +class Compass: + + def __init__(self,i2c_bus,ODR=ODR_200HZ,RNG=RNG_8G,OSR=OSR_512): + self._device = i2c_bus + self._address = I2CADDR_DEFAULT + self.output_range = RNG + self._declination = 0.0 + self._calibration = [[1.0, 0.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 1.0]] + self._device.scan() + time.sleep(0.1) + if self._read_byte(REG_CHIP_ID) != 0xFF: + raise AttributeError("Cannot find a QMC5883L") + + self.mode_cont = (MODE_CONT | ODR | RNG | OSR) + self.mode_stby = (MODE_STBY | ODR_10HZ | RNG_2G | OSR_64) + self.mode_continuous() + + def __del__(self): + """Once finished using the sensor, switch to standby mode.""" + self.mode_standby() + + def _write_byte(self, reg, val): + """Write memory address""" + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _read_byte(self, reg,nbytes=1): + """Read memory address""" + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def mode_continuous(self): + """Set the device in continuous read mode.""" + self._write_byte(REG_CONTROL_2, SOFT_RST) # Soft reset. + self._write_byte(REG_CONTROL_2, INT_ENB) # Disable interrupt. + self._write_byte(REG_RST_PERIOD, 0x01) # Define SET/RESET period. + self._write_byte(REG_CONTROL_1, self.mode_cont) # Set operation mode. + + def mode_standby(self): + """Set the device in standby mode.""" + self._write_byte(REG_CONTROL_2, SOFT_RST) + self._write_byte(REG_CONTROL_2, INT_ENB) + self._write_byte(REG_RST_PERIOD, 0x01) + self._write_byte(REG_CONTROL_1, self.mode_stby) # Set operation mode. + + def _read_word_2c(self, registry): + """Calculate the 2's complement of a two bytes value.""" + data=self._read_byte(registry,2) + val = (data[1] << 8) | data[0] + if val >= 0x8000: # 32768 + return val - 0x10000 # 65536 + else: + return val + + def ready(self): + return self._read_byte(REG_STATUS_1) + + def get_data(self): + """Read data from magnetic and temperature data registers.""" + i = 0 + [x, y, z, t] = [None, None, None, 0] + while i < 20: # Timeout after about 0.20 seconds. + status = self.ready() + if status & STAT_OVL: + # Some values have reached an overflow. + if self.output_range == RNG_2G: + raise AttributeError("Consider switching to RNG_8G output range") + else: + raise AttributeError("Magnetic sensor overflow") + if status & STAT_DOR: + # Previous measure was read partially, sensor in Data Lock. + x = self._read_word_2c(REG_XOUT_LSB) + y = self._read_word_2c(REG_YOUT_LSB) + z = self._read_word_2c(REG_ZOUT_LSB) + continue + if status & STAT_DRDY: + # Data is ready to read. + x = self._read_word_2c(REG_XOUT_LSB) + y = self._read_word_2c(REG_YOUT_LSB) + z = self._read_word_2c(REG_ZOUT_LSB) + t = self._read_word_2c(REG_TOUT_LSB) + break + else: + # Waiting for DRDY. + time.sleep(0.01) + i += 1 + return [x, y, z, t/100+20] + + def get_magnet_raw(self): + """Get the 3 axis values from magnetic sensor.""" + [x, y, z, t] = self.get_data() + return [x, y, z] + + def get_magnet(self): + """Return the horizontal magnetic sensor vector with (x, y) calibration applied.""" + [x, y, z] = self.get_magnet_raw() + if x is None or y is None: + [x1, y1] = [x, y] + else: + c = self._calibration + x1 = x * c[0][0] + y * c[0][1] + c[0][2] + y1 = x * c[1][0] + y * c[1][1] + c[1][2] + return [x1, y1] + + def get_bearing_raw(self): + """Horizontal bearing (in degrees) from magnetic value X and Y.""" + [x, y, z] = self.get_magnet_raw() + if x is None or y is None: + return None + else: + b = math.degrees(math.atan2(y, x)) + if b < 0: + b += 360.0 + return b + + def get_bearing(self): + """Horizontal bearing, adjusted by calibration and declination.""" + [x, y] = self.get_magnet() + if x is None or y is None: + return None + else: + b = math.degrees(math.atan2(y, x)) + if b < 0: + b += 360.0 + b += self._declination + if b < 0.0: + b += 360.0 + elif b >= 360.0: + b -= 360.0 + return round(b,2) + + def get_temp(self): + """Raw (uncalibrated) data from temperature sensor.""" + [x, y, z, t] = self.get_data() + return t + + def set_declination(self, value): + """Set the magnetic declination, in degrees.""" + try: + d = float(value) + if d < -180.0 or d > 180.0: + raise AttributeError('Declination must be >= -180 and <= 180') + else: + self._declination = d + except: + raise AttributeError('Declination must be a float value') + + def get_declination(self): + """Return the current set value of magnetic declination.""" + return self._declination + + def set_calibration(self, value): + """Set the 3x3 matrix for horizontal (x, y) magnetic vector calibration.""" + c = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] + try: + for i in range(0, 3): + for j in range(0, 3): + c[i][j] = float(value[i][j]) + self._calibration = c + except: + logging.error(u'Calibration must be a 3x3 float matrix.') + + def get_calibration(self): + """Return the current set value of the calibration matrix.""" + return self._calibration \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/qmi8658.py b/mixly/boards/default/micropython/build/lib/qmi8658.py new file mode 100644 index 00000000..6986d7f5 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/qmi8658.py @@ -0,0 +1,111 @@ +""" +QMI8658 + +Micropython library for the QMI8658(Accelerometer+Gyroscope) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from math import atan, sqrt, degrees +from micropython import const + +QMI8658_REG_DEVICE_ID = const(0x00) + +QMI8658_REG_Ctrl1 = const(0x02) #Serial Interface and Sensor Enable +QMI8658_REG_Ctrl2 = const(0x03) #Accelerometer Settings +QMI8658_REG_Ctrl3 = const(0x04) #Gyroscope Settings +QMI8658_REG_Ctrl5 = const(0x06) #Sensor Data Processing Settings +QMI8658_REG_Ctrl7 = const(0x08) #Sensor Data Processing Settings +QMI8658_REG_Ctrl9 = const(0x0A) #Host Commands +QMI8658_REG_StatusInt = const(0x2D) #Sensor Data Available and Lock Register Address +QMI8658_REG_DATA = const(0x33) + +Qmi8658AccRange_2g = 0 #/* +/- 2g range */ +Qmi8658AccRange_4g = 1 #/* +/- 4g range */ +Qmi8658AccRange_8g = 2 #/* +/- 8g range */ +Qmi8658AccRange_16g = 3 #/* +/- 16g range */ + +Qmi8658GyrRange_16dps = 0 #/* +-16 degrees per second. */ +Qmi8658GyrRange_32dps = 1 #/* +-32 degrees per second. */ +Qmi8658GyrRange_64dps = 2 #/* +-64 degrees per second. */ +Qmi8658GyrRange_128dps = 3 #/* +-128 degrees per second. */ +Qmi8658GyrRange_256dps = 4 #/* +-256 degrees per second. */ +Qmi8658GyrRange_512dps = 5 #/* +-512 degrees per second. */ +Qmi8658GyrRange_1024dps = 6 #/* +-1024 degrees per second. */ +Qmi8658GyrRange_2048dps = 7 #/* +-2048 degrees per second. */ + +Qmi8658Acc_Gyr_Odr_8000Hz = 0x00 #/* High resolution 8000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_4000Hz = 0x01 #/* High resolution 4000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_2000Hz = 0x02 #/* High resolution 2000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_1000Hz = 0x03 #/* High resolution 1000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_500Hz = 0x04 #/* High resolution 500Hz output rate. */ +Qmi8658Acc_Gyr_Odr_250Hz = 0x05 #/* High resolution 250Hz output rate. */ +Qmi8658Acc_Gyr_Odr_125Hz = 0x06 #/* High resolution 125Hz output rate. */ +Qmi8658Acc_Gyr_Odr_62_5Hz = 0x07 #/* High resolution 62.5Hz output rate. */ +Qmi8658Acc_Gyr_Odr_31_25Hz= 0x08 #/* High resolution 31.25Hz output rate. */ + +class QMI8658: + def __init__(self, i2c_bus,addr=0x6B,AccRange=Qmi8658AccRange_8g,GyrRange=Qmi8658GyrRange_2048dps,Acc_Gyr_Odr=Qmi8658Acc_Gyr_Odr_500Hz): + self._device = i2c_bus + self._address = addr + if self._chip_id() != 0x05: + raise AttributeError("Cannot find a QMI8658") + + self._wreg(QMI8658_REG_Ctrl9,0xA2) #做selftest,提高精度 + time.sleep(0.1) + self._wreg(QMI8658_REG_Ctrl1,0x60) + self._wreg(QMI8658_REG_Ctrl7,0x03) #启动 + self._wreg(QMI8658_REG_Ctrl2,(AccRange<< 4)|Acc_Gyr_Odr) #ACC-500HZ/8G + self._wreg(QMI8658_REG_Ctrl3,(GyrRange<< 4)|Acc_Gyr_Odr) #Gyr-500HZ/2048dps + self._wreg(QMI8658_REG_Ctrl5,0x75) #Gyr-14%,ACC-5.32% + self.gyr_lsb_div= 2**(11-GyrRange) + self.acc_lsb_div= 1<<(14-AccRange) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(QMI8658_REG_DEVICE_ID) + + def status(self): + return self._rreg(QMI8658_REG_StatusInt) + + def u2s(self,n): + return n if n < (1 << 15) else n - (1 << 16) + + @property + def getdata(self): + while self.status() == 0x81: + time.sleep(0.001) + _buffer=self._rreg(QMI8658_REG_DATA,14) + tmp= float(self.u2s(_buffer[1]<<8|_buffer[0]))/256.0 + acc_x=float(self.u2s(_buffer[3]<<8|_buffer[2]))/self.acc_lsb_div + acc_y=float(self.u2s(_buffer[5]<<8|_buffer[4]))/self.acc_lsb_div + acc_z=float(self.u2s(_buffer[7]<<8|_buffer[6]))/self.acc_lsb_div + gyr_x=float(self.u2s(_buffer[9]<<8|_buffer[8]))/self.gyr_lsb_div + gyr_y=float(self.u2s(_buffer[11]<<8|_buffer[10]))/self.gyr_lsb_div + gyr_z=float(self.u2s(_buffer[13]<<8|_buffer[12]))/self.gyr_lsb_div + return (acc_x,acc_y,acc_z),(gyr_x,gyr_y,gyr_z),round(tmp,2) + + def acceleration(self): + return self.getdata[0] + + def strength(self): + return sqrt(self.getdata[0][0]**2+self.getdata[0][1]**2+self.getdata[0][2]**2) + + def gyroscope(self): + return self.getdata[1] + + def temperature(self): + return self.getdata[2] + + def eulerangles(self,upright=False): + x,y,z = self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default/micropython/build/lib/radio.py b/mixly/boards/default/micropython/build/lib/radio.py new file mode 100644 index 00000000..a5ae46b6 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/radio.py @@ -0,0 +1,145 @@ +""" +Radio-ESP-NOW + +Micropython library for the Radio-ESP-NOW +======================================================= +@dahanzimin From the Mixly Team +""" +try: + from esp import espnow + version = 0 +except: + import espnow + version = 1 +from ubinascii import hexlify, unhexlify +import network + +class ESPNow(espnow.ESPNow): + def __init__(self, channel=None, txpower=20): + self._on_handle = {} + self._once_irq = True + self._nic = network.WLAN(network.STA_IF) #if version else network.WLAN(network.AP_IF) + self._nic.active(True) + if channel is not None: + self.set_channel(channel, txpower) + super().__init__() + self.active(True) + + def encrypt(self, peer, pmk, add_peer=True): + super().set_pmk((pmk + "0" *16)[:16].encode()) + if add_peer: + super().add_peer(unhexlify(peer), encrypt=True) + else: + super().del_peer(unhexlify(peer)) + + def send(self, peer='ffffffffffff', msg=''): + '''Send data after error reporting and effective processing''' + try: + _peer = unhexlify(peer) + return super().send(_peer, str(msg)) + except OSError as err: + if len(err.args) < 2: + raise err + if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT': + raise OSError("Radio(ESPNOW) is not activated, unable to transmit data") + elif err.args[1] == 'ESP_ERR_ESPNOW_IF': + self._nic.active(True) + elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND': + super().add_peer(_peer, channel=self.channel) + return super().send(_peer, str(msg)) + elif err.args[1] == 'ESP_ERR_ESPNOW_NO_MEM': + raise OSError("internal ESP-NOW buffers are full") + elif err.args[1] == 'ESP_ERR_ESPNOW_ARG': + raise OSError("invalid argument") + else: + raise err + + def recv(self): + '''Receive data''' + if self.any(): + host, msg = super().recv() + return hexlify(host).decode(),msg.decode() + else : + return None,None + + def set_channel(self, channel=1, txpower=20): + if not self._nic.isconnected(): + self._nic.config(channel=channel, txpower=txpower) + else: + print("Warning: WiFi is connected, the actual espnow channel is {}".format(self.channel)) + + def _cb_handle0(self, event_code, data): + '''Callback processing conversion''' + if self._on_handle: + if isinstance(self._on_handle, list): + for func in self._on_handle: + cmd = func.__name__.rfind('__') + if cmd != -1: + cmd=func.__name__[cmd+2:] + if cmd == str(data[1].decode()): + func(hexlify(data[0]).decode(), data[1].decode()) + else: + func(hexlify(data[0]).decode(), data[1].decode()) + elif isinstance(self._on_handle, dict): + mac = hexlify(data[0]).decode() + decoded_msg = str(data[1].decode()) + if '__all__' in self._on_handle: + self._on_handle['__all__'](mac, decoded_msg) + if decoded_msg in self._on_handle: + self._on_handle[decoded_msg](mac, decoded_msg) + else: + self._on_handle(hexlify(data[0]).decode(), data[1].decode()) + + def _cb_handle1(self, ee): + '''Callback processing conversion''' + host, msg = super().recv() + if self._on_handle: + if isinstance(self._on_handle, list): + for func in self._on_handle: + cmd = func.__name__.rfind('__') + if cmd != -1: + cmd=func.__name__[cmd+2:] + if cmd == str(msg.decode()): + func(hexlify(host).decode(), msg.decode()) + else: + func(hexlify(host).decode(), msg.decode()) + elif isinstance(self._on_handle, dict): + mac = hexlify(host).decode() + decoded_msg = str(msg.decode()) + if '__all__' in self._on_handle: + self._on_handle['__all__'](mac, decoded_msg) + if decoded_msg in self._on_handle: + self._on_handle[decoded_msg](mac, decoded_msg) + else: + self._on_handle(hexlify(host).decode(), msg.decode()) + + def recv_cb(self, *args): + '''Receive callback (single dictionary or lists)''' + if len(args) >= 2: + self._on_handle.update({args[0]: args[1]}) + else: + self._on_handle = args[0] + + if self._once_irq: + self._once_irq = False + if version == 0: + self.irq(self._cb_handle0) + else: + self.irq(self._cb_handle1) + + def info(self): + '''Get the paired Mac and rssi''' + _info=[] + for i in self.peers_table: + _info.append((hexlify(i).decode(), self.peers_table[i][0])) + return _info + + @property + def mac(self): + '''Get mac address''' + return hexlify(self._nic.config('mac')).decode() + + @property + def channel(self): + '''Get channel address''' + return self._nic.config('channel') diff --git a/mixly/boards/default/micropython/build/lib/rc522.py b/mixly/boards/default/micropython/build/lib/rc522.py new file mode 100644 index 00000000..5ecbfb08 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/rc522.py @@ -0,0 +1,279 @@ +""" +RC522 + +Micropython library for the RC522 RFID (I2C&SPI) +======================================================= +#Preliminary composition 20231204 + +dahanzimin From the Mixly Team +""" +import machine +from micropython import const + +RC_OK = True +RC_NOTAGERR = None +RC_ERR = False +RC_REQIDL = const(0x26) +RC_REQALL = const(0x52) +RC_AUTHENT1A = const(0x60) +RC_AUTHENT1B = const(0x61) +RC_Version = const(0x37) + +class RC522: + def __init__(self, drive_bus,cs_pin=None,addr=0x28): + self._device= drive_bus + if type(drive_bus) in [machine.I2C,machine.SoftI2C]: + self._type=True + self._address = addr + elif type(drive_bus) in [machine.SPI,machine.SoftSPI]: + self._type=False + self._cs = machine.Pin(cs_pin, machine.Pin.OUT) + else: + raise ValueError("RC522 only supports I2C and SPI") + + self.init() + self.add_list=[1,2,4,5,6,8,9,10,12,13,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,56,57,58,60,61,62] + + def _wreg(self, reg, val): + '''Write memory address''' + if self._type: + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + else: + self._cs.value(0) + self._device.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))) + self._device.write(b'%c' % int(0xff & val)) + self._cs.value(1) + + def _rreg(self, reg): + '''Read memory address''' + if self._type: + return self._device.readfrom_mem(self._address, reg, 1)[0] + else: + self._cs.value(0) + self._device.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80))) + val = self._device.read(1) + self._cs.value(1) + return val[0] + + def _sflags(self, reg, mask): + self._wreg(reg, self._rreg(reg) | mask) + + def _cflags(self, reg, mask): + self._wreg(reg, self._rreg(reg) & (~mask)) + + def _tocard(self, cmd, send): + recv = [] + bits = 0 + irq_en = 0 + wait_irq =0 + n = 0 + stat = RC_ERR + if cmd == 0x0E: + irq_en = 0x12 + wait_irq = 0x10 + elif cmd == 0x0C: + irq_en = 0x77 + wait_irq = 0x30 + self._wreg(0x02, irq_en) + self._cflags(0x04, 0x80) + self._sflags(0x0A, 0x80) + self._wreg(0x01, 0x00) + for c in send: + self._wreg(0x09, c) + self._wreg(0x01, cmd) + + if cmd == 0x0C: + self._sflags(0x0D, 0x80) + + i = 100 + while True: + n = self._rreg(0x04) + i -= 1 + if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)): + break + + self._cflags(0x0D, 0x80) + if i: + if (self._rreg(0x06) & 0x1B) == 0x00: + stat = RC_OK + + if n & irq_en & 0x01: + stat = RC_NOTAGERR + elif cmd == 0x0C: + n = self._rreg(0x0A) + lbits = self._rreg(0x0C) & 0x07 + if lbits != 0: + bits = (n - 1) * 8 + lbits + else: + bits = n * 8 + if n == 0: + n = 1 + elif n > 16: + n = 16 + for _ in range(n): + recv.append(self._rreg(0x09)) + else: + stat = RC_ERR + return stat, recv, bits + + def _crc(self, data): + self._cflags(0x05, 0x04) + self._sflags(0x0A, 0x80) + for c in data: + self._wreg(0x09, c) + self._wreg(0x01, 0x03) + i = 0xFF + while True: + n = self._rreg(0x05) + i -= 1 + if not ((i != 0) and not (n & 0x04)): + break + return [self._rreg(0x22), self._rreg(0x21)] + + def init(self): + self.reset() + self._wreg(0x2A, 0x8D) + self._wreg(0x2B, 0x3E) + self._wreg(0x2D, 30) + self._wreg(0x2C, 0) + self._wreg(0x15, 0x40) + self._wreg(0x11, 0x3D) + self._wreg(0x26, 0x68) + #A32NQ32C3 Additional Register Configuration + if self._rreg(RC_Version) == 0x82: + self._wreg(0x12, 0x0) + self._wreg(0x13, 0x0) + self._wreg(0x14, 0x84) + self._wreg(0x18, 0x33) + self._wreg(0x0c, 0x10) + self.antenna_on() + + def reset(self): + self._wreg(0x01, 0x0F) + + def antenna_on(self, on=True): + if on and ~(self._rreg(0x14) & 0x03): + self._sflags(0x14, 0x03) + else: + self._cflags(0x14, 0x03) + + def request(self, mode): + self._wreg(0x0D, 0x07) + stat, recv, bits = self._tocard(0x0C, [mode]) + if (stat != RC_OK) | (bits != 0x10): + stat = RC_ERR + return stat, bits + + def anticoll(self): + ser_chk = 0 + ser = [0x93, 0x20] + self._wreg(0x0D, 0x00) + (stat, recv, bits) = self._tocard(0x0C, ser) + + if stat == RC_OK: + if len(recv) == 5: + for i in range(4): + ser_chk = ser_chk ^ recv[i] + if ser_chk != recv[4]: + stat = RC_ERR + else: + stat = RC_ERR + return stat, recv + + def select_tag(self, ser): + buf = [0x93, 0x70] + ser[:5] + buf += self._crc(buf) + (stat, recv, bits) = self._tocard(0x0C, buf) + return RC_OK if (stat == RC_OK) and (bits == 0x18) else RC_ERR + + def auth(self, mode, addr, sect, ser): + return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0] + + def stop_crypto1(self): + self._cflags(0x08, 0x08) + + def read(self, addr): + data = [0x30, addr] + data += self._crc(data) + (stat, recv, _) = self._tocard(0x0C, data) + return recv if stat == RC_OK else None + + def write(self, addr, data): + buf = [0xA0, addr] + buf += self._crc(buf) + (stat, recv, bits) = self._tocard(0x0C, buf) + + if not (stat == RC_OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): + stat = RC_ERR + else: + buf = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + for i in range(len(data)): + buf[i]=data[i] + buf += self._crc(buf) + (stat, recv, bits) = self._tocard(0x0C, buf) + if not (stat == RC_OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): + stat = RC_ERR + return stat + + def read_card(self,add,x='ALL'):#0:all,i:id,2:content + if add>=47: + raise AttributeError("Out of address range") + stat, tag_type = self.request(RC_REQALL) + if stat !=RC_OK: + stat, tag_type = self.request(RC_REQALL) + if stat == RC_OK: + (stat, raw_uid) = self.anticoll() + if stat == RC_OK: + if self.select_tag(raw_uid) == RC_OK: + key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] + if self.auth(RC_AUTHENT1A, self.add_list[add], key, raw_uid) == RC_OK: + card = self.read(self.add_list[add]) + try: + card = bytes(card).decode().replace("\x00", '') if card else None + except: + card = bytes(card) if card else None + self.stop_crypto1() + if x == "ALL": + return int('{}{}{}{}'.format(raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])), card + elif x == "id": + return int('{}{}{}{}'.format(raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])) + elif x == "content": + return card + + def write_card(self, data,add): + if add>=47: + raise AttributeError("Out of address range") + stat, tag_type = self.request(RC_REQALL) + if stat !=RC_OK: + stat, tag_type = self.request(RC_REQALL) + if stat == RC_OK: + (stat, raw_uid) = self.anticoll() + if stat == RC_OK: + if self.select_tag(raw_uid) == RC_OK: + key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] + if self.auth(RC_AUTHENT1A, self.add_list[add], key, raw_uid) == RC_OK: + try: + data =list(data.encode()) + except: + data =list(data) + if len(data)>16: + raise AttributeError("Input must be less than 16 bytes") + stat = self.write(self.add_list[add], data) + self.stop_crypto1() + if stat == RC_OK: + print('Data written to card') + return RC_OK + else: + print('Failed to write data to card') + return RC_ERR + else: + print('Authentication error') + return RC_ERR + else: + print('Failed to select tag') + return RC_ERR + else: + return RC_ERR + + def scan_card(self,stat=RC_REQIDL): + return self.request(stat)[0] diff --git a/mixly/boards/default/micropython/build/lib/rfm98.py b/mixly/boards/default/micropython/build/lib/rfm98.py new file mode 100644 index 00000000..194b9819 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/rfm98.py @@ -0,0 +1,239 @@ +""" +RFM98 + +Micropython library for the RFM98 LoRa +======================================================= +#Preliminary composition 20220406 +#Rebuild and optimize execution 20220412 +#Repair receive mode 20220428 + +dahanzimin From the Mixly Team +""" +import gc +import time +from machine import Pin +from micropython import const + +_REG_FIFO = const(0x00) +_REG_OP_MODE = const(0x01) +_REG_FRF_MSB = const(0x06) +_REG_FRF_MID = const(0x07) +_REG_FRF_LSB = const(0x08) +_REG_PA_CONFIG = const(0x09) +_REG_LNA = const(0x0C) +_REG_FIFO_ADDR_PTR = const(0x0D) +_REG_FIFO_TX_BASE_ADDR = const(0x0E) +_REG_FIFO_RX_BASE_ADDR = const(0x0F) +_REG_FIFO_RX_CURRENT_ADDR = const(0x10) +_REG_IRQ_FLAGS = const(0x12) +_REG_RX_NB_BYTES = const(0x13) +_REG_PKT_SNR_VALUE = const(0x19) +_REG_PKT_RSSI_VALUE = const(0x1A) +_REG_MODEM_CONFIG1 = const(0x1D) +_REG_MODEM_CONFIG2 = const(0x1E) +_REG_PREAMBLE_MSB = const(0x20) +_REG_PREAMBLE_LSB = const(0x21) +_REG_PAYLOAD_LENGTH = const(0x22) +_REG_MODEM_CONFIG3 = const(0x26) +_REG_DIO_MAPPING1 = const(0x40) +_REG_DIO_MAPPING2 = const(0x41) +_REG_VERSION = const(0x42) +_REG_PA_DAC = const(0x4D) +_DETECTION_OPTIMIZE = const(0x31) +_DETECTION_THRESHOLD = const(0x37) + +_MODE_LONG_RANGE_MODE = const(0x88) +_MODE_SLEEP = const(0x00) +_MODE_STDBY = const(0x01) +_MODE_TX = const(0x03) +_MODE_RX = const(0x05) + +class RFM98: + def __init__(self,spi,cs_pin,frequency_mhz=433.0,signal_bandwidth=125E3,coding_rate=5,spreading_factor=7,**kw): + self._spi = spi + self._pin_ss = Pin(cs_pin, Pin.OUT) + self._frequency_mhz=frequency_mhz + self._signal_bandwidth=signal_bandwidth + self._coding_rate=coding_rate + self._spreading_factor=spreading_factor + self._kw=kw + self.init() + + def init(self): + for i in range(6): + if self._read_u8(_REG_VERSION) == 18: # No device type check! + break + if i >=5: + raise AttributeError("Cannot find a RFM9x") + time.sleep(1) + + self.sleep() + time.sleep(0.01) + if self._read_u8(_REG_OP_MODE) != (_MODE_LONG_RANGE_MODE | _MODE_SLEEP): + raise RuntimeError("Failed to configure radio for LoRa mode, check wiring!") + self._write_u8(_REG_FIFO_TX_BASE_ADDR, 0x00) # Setup entire 256 byte FIFO + self._write_u8(_REG_FIFO_RX_BASE_ADDR, 0x00) + + self.idle() + self.coding_rate(self._coding_rate) # CR: 5...8 + self.frequency_mhz(self._frequency_mhz) # Set frequency_mhz 433±10.00 + self.signal_bandwidth(self._signal_bandwidth) # BW: 7.8...500 kHz + self.spreading_factor(self._spreading_factor) # SF: 6..12 + self.enable_crc(self._kw.get('enable_crc', True)) # Set enable_crc + self.preamble_length(self._kw.get('preamble_length', 6)) + self.tx_power(self._kw.get('tx_power', 16),self._kw.get('high_power', True)) + + self._write_u8(_REG_MODEM_CONFIG3, 0x04) #set AGC - True + if 1000 /(self._signal_bandwidth / 2**self._spreading_factor) > 16: + self._write_u8(_REG_MODEM_CONFIG3, self._read_u8(_REG_MODEM_CONFIG3) | 0x08) + + def transfer(self, address, value = 0x00): + response = bytearray(1) + self._pin_ss.value(0) + self._spi.write(bytes([address])) + self._spi.write_readinto(bytes([value]), response) + self._pin_ss.value(1) + return response + + def _read_u8(self, address): + response = self.transfer(address & 0x7f) + return int.from_bytes(response, 'big') + + def _write_u8(self, address, value): + self.transfer(address | 0x80, value) + + def idle(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_STDBY) + + def sleep(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_SLEEP) + + def listen(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_RX) + self._write_u8(_REG_DIO_MAPPING1, 0x00) + self._write_u8(_REG_DIO_MAPPING2, 0x40) + + def transmit(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_TX) + self._write_u8(_REG_DIO_MAPPING1, 0x01) + self._write_u8(_REG_DIO_MAPPING2, 0x00) + + def preamble_length(self, val): + self._write_u8(_REG_PREAMBLE_MSB, (val >> 8) & 0xFF) + self._write_u8(_REG_PREAMBLE_LSB, val & 0xFF) + + def frequency_mhz(self, val): + if val < 410 or val > 525: + raise RuntimeError("frequency_mhz must be between 410 and 525") + frf = int((val * 1000000.0) /(32000000.0 / 524288)) & 0xFFFFFF + self._write_u8(_REG_FRF_MSB, frf >> 16) + self._write_u8(_REG_FRF_MID, (frf >> 8) & 0xFF) + self._write_u8(_REG_FRF_LSB, frf & 0xFF) + + def tx_power(self, val,high_power=True): + if high_power: + assert 5 <= val <= 23 + if val > 20: + self._write_u8(_REG_PA_DAC, 0x07) + val -= 3 + else: + self._write_u8(_REG_PA_DAC, 0x04) + self._write_u8(_REG_PA_CONFIG, 0x80 | (val - 5)) + else: + assert -1 <= val <= 14 + self._write_u8(_REG_PA_CONFIG, 0x70 | (val +1)) + + def packet_rssi(self): #last RSSI reading + return self._read_u8(_REG_PKT_RSSI_VALUE)-157 + + def packet_snr(self): #last SNR reading + snr_byte = self._read_u8(_REG_PKT_SNR_VALUE) + return snr_byte/4 if snr_byte<=127 else (snr_byte -256 )/4 + + def signal_bandwidth(self, val): + bw_bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000) + for bw_id, cutoff in enumerate(bw_bins): + if val <= cutoff: + break + else: + bw_id = 9 + self._write_u8(_REG_MODEM_CONFIG1,(self._read_u8(_REG_MODEM_CONFIG1) & 0x0F) | (bw_id << 4)) + if val >= 500000: + self._write_u8(_DETECTION_OPTIMIZE,(self._read_u8(_DETECTION_OPTIMIZE) | 0x80)) + self._write_u8(0x36, 0x02) + self._write_u8(0x3A, 0x7F) + else: + self._write_u8(_DETECTION_OPTIMIZE,(self._read_u8(_DETECTION_OPTIMIZE) & 0x7F)) + self._write_u8(0x36, 0x03) + if val == 7800: + self._write_u8(0x2F, 0x48) + elif val >= 62500: + self._write_u8(0x2F, 0x40) + else: + self._write_u8(0x2F, 0x44) + self._write_u8(0x30, 0) + + def coding_rate(self, val): + denominator = min(max(val, 5), 8) + cr_id = denominator - 4 + self._write_u8(_REG_MODEM_CONFIG1,(self._read_u8(_REG_MODEM_CONFIG1) & 0xF1) | (cr_id << 1)) + + def spreading_factor(self, val): + val = min(max(val, 6), 12) + self._write_u8(_DETECTION_OPTIMIZE,self._read_u8(_DETECTION_OPTIMIZE)|0x05 if val == 6 else self._read_u8(_DETECTION_OPTIMIZE)|0x03) + self._write_u8(_DETECTION_THRESHOLD, 0x0C if val == 6 else 0x0A) + self._write_u8(_REG_MODEM_CONFIG2,((self._read_u8(_REG_MODEM_CONFIG2) & 0x0F)| ((val << 4) & 0xF0))) + + def enable_crc(self, val): + if val: + self._write_u8(_REG_MODEM_CONFIG2,self._read_u8(_REG_MODEM_CONFIG2) | 0x04) + else: + self._write_u8(_REG_MODEM_CONFIG2,self._read_u8(_REG_MODEM_CONFIG2) & 0xFB) + + def irq_done(self): #irq status + return self._read_u8(_REG_IRQ_FLAGS) + + def send(self,msg,timeout=2): + self.idle() # Stop receiving to clear FIFO and keep it clear. + self._write_u8(_REG_FIFO_ADDR_PTR, 0x00) # FIFO starts at 0. + if isinstance(msg, str): + msg = msg.encode() + size = min(len(msg), 255) + for i in range(size): # write data + self._write_u8(_REG_FIFO, msg[i]) # Write payload. + self._write_u8(_REG_PAYLOAD_LENGTH, size) # Write payload and header length. + self.transmit() # Turn on transmit mode to send out the packet. + + timed_out = False + start = time.ticks_ms() + while not timed_out and not((self._read_u8(_REG_IRQ_FLAGS) & 0x8) >> 3): + if time.ticks_diff(time.ticks_ms(), start) >= timeout * 1000: + timed_out = True + + self.idle() # Enter idle mode to stop receiving other packets. + gc.collect() + self._write_u8(_REG_IRQ_FLAGS, 0xFF) # Clear interrupt. + return not timed_out + + def recv(self): + if self._read_u8(_REG_OP_MODE) != (_MODE_LONG_RANGE_MODE | _MODE_RX): + self.listen() # Enter receive mode + + flags=self.irq_done() + if flags & 0x40: + self.idle() # Enter idle mode to stop receiving other packets. + fifo_length = self._read_u8(_REG_RX_NB_BYTES) # Read the length of the FIFO. + if fifo_length > 0: # Read the data from the FIFO. + self._write_u8(_REG_FIFO_ADDR_PTR, self._read_u8(_REG_FIFO_RX_CURRENT_ADDR)) + packet = bytearray() + for i in range(fifo_length): + packet.append(self._read_u8(_REG_FIFO)) # Read the packet. + self._write_u8(_REG_IRQ_FLAGS, 0xFF) # Clear interrupt. + gc.collect() + try : + return bytes(packet).decode() + except: + return bytes(packet) + elif flags== 0x15: + print("Timeout not handled , overflow error,will restart!") + self.init() \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/rtctime.py b/mixly/boards/default/micropython/build/lib/rtctime.py new file mode 100644 index 00000000..733901a2 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/rtctime.py @@ -0,0 +1,69 @@ +"""RTC Time""" +import gc +from time import * +from machine import RTC +import usocket as socket +import ustruct as struct + +# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 +NTP_DELTA = 3155673600 +_weekdayname = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun") +_monthname = (None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",) + +def ntptime(host="pool.ntp.org", utc=28800): + NTP_QUERY = bytearray(48) + NTP_QUERY[0] = 0x1B + addr = socket.getaddrinfo(host, 123)[0][-1] + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.settimeout(1) + res = s.sendto(NTP_QUERY, addr) + msg = s.recv(48) + finally: + del addr + s.close() + gc.collect() + val = struct.unpack("!I", msg[40:44])[0] + return gmtime(val - NTP_DELTA + utc) + +# There's currently no timezone support in MicroPython, and the RTC is set in UTC time. +def settime(times): + if isinstance(times, str): + try: + times = eval(times) + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0)) + else: + raise ValueError("Settime needs a type of length 6~8") + +def strtime(times=None): + if times is None: + times = localtime() + if isinstance(times, str): + try: + times = eval(times) + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format(*times) + else: + raise ValueError("Settime needs a type of length 6~8") + +def rfc1123_time(times=None, utc=28800): + if times is None: + times = localtime() + if isinstance(times, str): + try: + times = eval(times) + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + times = localtime(mktime(times) - utc) + return '{0}, {1:02d} {2} {3:04d} {4:02d}:{5:02d}:{6:02d} GMT'.format(_weekdayname[times[6]], times[2], _monthname[times[1]], times[0], times[3], times[4], times[5]) + else: + raise ValueError("Settime needs a type of length 6~8") diff --git a/mixly/boards/default/micropython/build/lib/sc7a20.py b/mixly/boards/default/micropython/build/lib/sc7a20.py new file mode 100644 index 00000000..f73c6193 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/sc7a20.py @@ -0,0 +1,72 @@ +""" +SC7A20 + +Micropython library for the SC7A20 Accelerometer +================================================= +#Preliminary composition 20240312 + +@dahanzimin From the Mixly Team +""" +import time +from math import atan,sqrt,degrees +from micropython import const + +SC7A20_ADDRESS = const(0x19) +SC7A20_REG_ID = const(0x0F) +SC7A20_REG_CTRL1 = const(0x20) +SC7A20_REG_CTRL2 = const(0x21) +SC7A20_REG_CTRL3 = const(0x22) +SC7A20_REG_CTRL4 = const(0x23) +SC7A20_REG_DATA = const(0x28) + + #2g 4g 8g 16g +_Range_X = (1024,512,256,128) + +class SC7A20: + + def __init__(self, i2c_bus, set_range=2, front=False): + self._device = i2c_bus + self._address = SC7A20_ADDRESS + self._range = set_range #default 8g range + self._front = front + + if self._rreg(SC7A20_REG_ID) != 0x11: + raise AttributeError("Cannot find a SC7A20") + self._wreg(SC7A20_REG_CTRL1, 0X77) #400HZ,xyz使能 + self._wreg(SC7A20_REG_CTRL2, 0X00) #禁止高通滤波模式 + self._wreg(SC7A20_REG_CTRL3, 0X00) #禁止中断 + self._wreg(SC7A20_REG_CTRL4, 0X00 | set_range << 4) #连续更新,设置量程 + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, 1)[0] + + def u2s(self, n): + return n if n < (1 << 7) else n - (1 << 8) + + @property + def getdata(self): + x_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 1)) << 8 | self._rreg(SC7A20_REG_DATA + 0)) >> 4) / _Range_X[self._range] + y_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 3)) << 8 | self._rreg(SC7A20_REG_DATA + 2)) >> 4) / _Range_X[self._range] + z_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 5)) << 8 | self._rreg(SC7A20_REG_DATA + 4)) >> 4) / _Range_X[self._range] + return (-x_acc, y_acc, z_acc, None) if self._front else (x_acc, y_acc, z_acc, None) + + def acceleration(self): + return self.getdata[0:3] + + def strength(self): + from math import sqrt + return sqrt(self.getdata[0]**2+self.getdata[1]**2+self.getdata[2]**2) + + def temperature(self): + return self.getdata[3] + + def eulerangles(self,upright=False): + x, y, z = self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default/micropython/build/lib/sdcard.py b/mixly/boards/default/micropython/build/lib/sdcard.py new file mode 100644 index 00000000..54425efb --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/sdcard.py @@ -0,0 +1,231 @@ +""" +MicroPython driver for SD cards using SPI bus. +""" +import time +from machine import Pin +from micropython import const + +_CMD_TIMEOUT = const(100) +_R1_IDLE_STATE = const(1 << 0) +_R1_ILLEGAL_COMMAND = const(1 << 2) +_TOKEN_CMD25 = const(0xFC) +_TOKEN_STOP_TRAN = const(0xFD) +_TOKEN_DATA = const(0xFE) + +class SDCard: + def __init__(self, spi, cs_pin=None, baudrate=50000000): + self.spi = spi + self.cs = Pin(cs_pin, Pin.OUT, value=1) if cs_pin else None + self.cmdbuf = bytearray(6) + self.dummybuf = bytearray(512) + self.tokenbuf = bytearray(1) + for i in range(512): + self.dummybuf[i] = 0xFF + self.dummybuf_memoryview = memoryview(self.dummybuf) + # initialise the card + self.init_card(baudrate) + + def init_spi(self, baudrate): + self.spi.init(baudrate=baudrate, phase=0, polarity=0) + + def init_card(self, baudrate): + # init SPI bus; use low data rate for initialisation + self.init_spi(100000) + # clock card at least 100 cycles with cs high + for i in range(16): + self.spi.write(b"\xff") + # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) + for _ in range(5): + if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: + break + else: + raise OSError("no SD card") + # CMD8: determine card version + r = self.cmd(8, 0x01AA, 0x87, 4) + if r == _R1_IDLE_STATE: + self.init_card_v2() + elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): + self.init_card_v1() + else: + raise OSError("couldn't determine SD card version") + # CMD9: response R2 (R1 byte + 16-byte block read) + if self.cmd(9, 0, 0, 0, False) != 0: + raise OSError("no response from SD card") + csd = bytearray(16) + self.readinto(csd) + if csd[0] & 0xC0 == 0x40: # CSD version 2.0 + self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024 + elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB) + c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6 + c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7 + read_bl_len = csd[5] & 0b1111 + capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len) + self.sectors = capacity // 512 + else: + raise OSError("SD card CSD format not supported") + # CMD16: set block length to 512 bytes + if self.cmd(16, 512, 0) != 0: + raise OSError("can't set 512 block size") + # set to high data rate now that it's initialised + self.init_spi(baudrate) + + def init_card_v1(self): + for i in range(_CMD_TIMEOUT): + time.sleep_ms(50) + self.cmd(55, 0, 0) + if self.cmd(41, 0, 0) == 0: + # SDSC card, uses byte addressing in read/write/erase commands + self.cdv = 512 + # print("[SDCard] v1 card") + return + raise OSError("timeout waiting for v1 card") + + def init_card_v2(self): + for i in range(_CMD_TIMEOUT): + time.sleep_ms(50) + self.cmd(58, 0, 0, 4) + self.cmd(55, 0, 0) + if self.cmd(41, 0x40000000, 0) == 0: + self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte + ocr = self.tokenbuf[0] # get first byte of response, which is OCR + if not ocr & 0x40: + # SDSC card, uses byte addressing in read/write/erase commands + self.cdv = 512 + else: + # SDHC/SDXC card, uses block addressing in read/write/erase commands + self.cdv = 1 + # print("[SDCard] v2 card") + return + raise OSError("timeout waiting for v2 card") + + def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False): + if self.cs: self.cs(0) + + # create and send the command + buf = self.cmdbuf + buf[0] = 0x40 | cmd + buf[1] = arg >> 24 + buf[2] = arg >> 16 + buf[3] = arg >> 8 + buf[4] = arg + buf[5] = crc + self.spi.write(buf) + + if skip1: + self.spi.readinto(self.tokenbuf, 0xFF) + # wait for the response (response[7] == 0) + for i in range(_CMD_TIMEOUT): + self.spi.readinto(self.tokenbuf, 0xFF) + response = self.tokenbuf[0] + if not (response & 0x80): + if final < 0: + self.spi.readinto(self.tokenbuf, 0xFF) + final = -1 - final + for j in range(final): + self.spi.write(b"\xff") + if release: + if self.cs: self.cs(1) + self.spi.write(b"\xff") + return response + if self.cs: self.cs(1) + self.spi.write(b"\xff") + return -1 + + def readinto(self, buf): + if self.cs: self.cs(0) + for i in range(_CMD_TIMEOUT): + self.spi.readinto(self.tokenbuf, 0xFF) + if self.tokenbuf[0] == _TOKEN_DATA: + break + time.sleep_ms(1) + else: + if self.cs: self.cs(1) + raise OSError("timeout waiting for response") + mv = self.dummybuf_memoryview + if len(buf) != len(mv): + mv = mv[: len(buf)] + self.spi.write_readinto(mv, buf) + self.spi.write(b"\xff") + self.spi.write(b"\xff") + if self.cs: self.cs(1) + self.spi.write(b"\xff") + + def write(self, token, buf): + if self.cs: self.cs(0) + self.spi.read(1, token) + self.spi.write(buf) + self.spi.write(b"\xff") + self.spi.write(b"\xff") + if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05: + if self.cs: self.cs(1) + self.spi.write(b"\xff") + return + while self.spi.read(1, 0xFF)[0] == 0: + pass + if self.cs: self.cs(1) + self.spi.write(b"\xff") + + def write_token(self, token): + if self.cs: self.cs(0) + self.spi.read(1, token) + self.spi.write(b"\xff") + while self.spi.read(1, 0xFF)[0] == 0x00: + pass + if self.cs: self.cs(1) + self.spi.write(b"\xff") + + def readblocks(self, block_num, buf): + # workaround for shared bus, required for (at least) some Kingston + self.spi.write(b"\xff") + + nblocks = len(buf) // 512 + assert nblocks and not len(buf) % 512, "Buffer length is invalid" + if nblocks == 1: + # CMD17: set read address for single block + if self.cmd(17, block_num * self.cdv, 0, release=False) != 0: + # release the card + if self.cs: self.cs(1) + raise OSError(5) # EIO + # receive the data and release card + self.readinto(buf) + else: + # CMD18: set read address for multiple blocks + if self.cmd(18, block_num * self.cdv, 0, release=False) != 0: + if self.cs: self.cs(1) + raise OSError(5) # EIO + offset = 0 + mv = memoryview(buf) + while nblocks: + self.readinto(mv[offset : offset + 512]) + offset += 512 + nblocks -= 1 + if self.cmd(12, 0, 0xFF, skip1=True): + raise OSError(5) # EIO + + def writeblocks(self, block_num, buf): + # workaround for shared bus, required for (at least) some Kingston + self.spi.write(b"\xff") + nblocks, err = divmod(len(buf), 512) + assert nblocks and not err, "Buffer length is invalid" + if nblocks == 1: + # CMD24: set write address for single block + if self.cmd(24, block_num * self.cdv, 0) != 0: + raise OSError(5) # EIO + self.write(_TOKEN_DATA, buf) + else: + # CMD25: set write address for first block + if self.cmd(25, block_num * self.cdv, 0) != 0: + raise OSError(5) # EIO + offset = 0 + mv = memoryview(buf) + while nblocks: + self.write(_TOKEN_CMD25, mv[offset : offset + 512]) + offset += 512 + nblocks -= 1 + self.write_token(_TOKEN_STOP_TRAN) + + def ioctl(self, op, arg): + if op == 4: # get number of blocks + return self.sectors + if op == 5: # get block size in bytes + return 512 diff --git a/mixly/boards/default/micropython/build/lib/seniverse_api.py b/mixly/boards/default/micropython/build/lib/seniverse_api.py new file mode 100644 index 00000000..3d8beae2 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/seniverse_api.py @@ -0,0 +1,217 @@ +""" +Seniverse Weather API + +MicroPython library for Seniverse Weather API +======================================================= + +#Preliminary composition 20220420 +#https://www.seniverse.com/api + +dahanzimin From the Mixly Team +""" + +import json +import urequests + +_weather_now="http://api.seniverse.com/v3/weather/now.json?" #天气实况 +_weather_daily="http://api.seniverse.com/v3/weather/daily.json?" #逐日天气预报 +_weather_hourly="http://api.seniverse.com/v3/weather/hourly.json?" #逐时天气预报 +_weather_alarm="http://api.seniverse.com/v3/weather/alarm.json?" #气象灾害预警 +_life_suggestion="http://api.seniverse.com/v3/life/suggestion.json?" #生活指数 +_air_now="http://api.seniverse.com/v3/air/now.json?" #空气质量实况 +_air_daily="http://api.seniverse.com/v3/air/daily.json?" #逐日空气质量预报 +_air_hourly="http://api.seniverse.com/v3/air/hourly.json?" #逐时空气质量预报 +_tide_daily="http://api.seniverse.com/v3/tide/daily.json?" #逐时潮汐预报 +_geo_sun="http://api.seniverse.com/v3/geo/sun.json?" #日出日落 +_geo_moon="http://api.seniverse.com/v3/geo/moon.json?" #月出月落和月相 +_location_search="http://api.seniverse.com/v3/location/search.json?" #城市搜索 + +#数据请求 +class API_BASE: + _results = None + def _urequests_api(self, url): + try: + results=json.loads(urequests.post(url).text) + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected",e) + + if "status" in results.keys(): + raise ValueError(results["status"]) + if "results" in results.keys(): + return results["results"] + +#天气实况 https://docs.seniverse.com/api/weather/now.html +class Weather_now(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}".format(_weather_now, key, location) + self._results = self._urequests_api(url)[0]['now'] + + def analysis(self, key=None): + if key is None: + return self._results + else: + return self._results[key] + +Weather_now = Weather_now() + +#逐日天气预报 https://docs.seniverse.com/api/weather/daily.html +class Weather_daily(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_weather_daily, key, location, days) + self._results = self._urequests_api(url)[0]['daily'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Weather_daily = Weather_daily() + +#逐时天气预报 https://docs.seniverse.com/api/weather/hourly.html +class Weather_hourly(API_BASE): + def request(self, key, location, hours=1): + url = "{}key={}&location={}&hours={}".format(_weather_hourly, key, location, hours) + self._results = self._urequests_api(url)[0]['hourly'] + + def analysis(self, hours=1, key=None): + if key is None: + return self._results[hours] + else: + return self._results[hours][key] + +#Weather_hourly = Weather_hourly() #暂不开启 + +#空气质量实况 https://docs.seniverse.com/api/air/now.html +class Air_now(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}&scope=city".format(_air_now, key, location) + self._results = self._urequests_api(url)[0]['air']['city'] + + def analysis(self, key=None): + if key is None: + return self._results + else: + return self._results[key] + +Air_now = Air_now() + +#逐日空气质量预报 https://docs.seniverse.com/api/air/daily5d.html +class Air_daily(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_air_daily, key, location, days) + self._results = self._urequests_api(url)[0]['daily'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Air_daily= Air_daily() + +#逐时空气质量预报 https://docs.seniverse.com/api/air/hourly5d.html +class Air_hourly(API_BASE): + def request(self, key, location, hours=1): + url = "{}key={}&location={}&hours={}&days=1".format(_air_hourly, key, location, hours) + self._results = self._urequests_api(url)[0]['hourly'] + + def analysis(self, hours=1, key=None): + if key is None: + return self._results[hours] + else: + return self._results[hours][key] + +#Air_hourly = Air_hourly() #暂不开启 + +#气象灾害预警 https://docs.seniverse.com/api/weather/alarm.html +class Weather_alarm(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}".format(_weather_alarm, key, location) + results = self._urequests_api(url)[0]['alarms'] + self._results = results[0] if results else {} + + def analysis(self, key=None): + if key is None: + return self._results + if key in self._results.keys(): + return self._results[key] + +Weather_alarm = Weather_alarm() + +#生活指数 https://docs.seniverse.com/api/life/suggestion.html +class Life_suggestion(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}".format(_life_suggestion, key, location) + self._results = self._urequests_api(url)[0]['suggestion'] + + def analysis(self, key=None, brief=False): + if key is None: + return self._results + else: + return self._results[key]['brief'] if brief else self._results[key]['details'] + +Life_suggestion = Life_suggestion() + +#24时潮汐预报 https://docs.seniverse.com/api/ocean/tide.html +class Tide_daily(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}&days=1".format(_tide_daily, key, location) + self._results = self._urequests_api(url)[0]['ports'][0]['data'][0] + + def analysis(self, key=None): + if key is None: + return self._results + else: + key = key.split(',') + if len(key) == 1: + return self._results[key[0]] + if len(key) == 2: + return self._results['range'][int(key[0])][key[1]] + +Tide_daily = Tide_daily() + +#日出日落 https://docs.seniverse.com/api/geo/sun.html +class Geo_sun(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_geo_sun, key, location, days) + self._results = self._urequests_api(url)[0]['sun'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Geo_sun = Geo_sun() + +#月出月落和月相 https://docs.seniverse.com/api/geo/moon.html +class Geo_moon(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_geo_moon, key, location, days) + self._results = self._urequests_api(url)[0]['moon'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Geo_moon = Geo_moon() + +#城市搜索 https://docs.seniverse.com/api/fct/search.html +class Location_search(API_BASE): + def request(self, key, location): + url = "{}key={}&q={}&limit=50".format(_location_search, key, location) + results = self._urequests_api(url) + self._results = results[0] if results else {} + + def analysis(self, key=None): + if key is None: + return self._results + else: + if key in self._results.keys(): + return self._results[key] + +Location_search = Location_search() + \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/servo.py b/mixly/boards/default/micropython/build/lib/servo.py new file mode 100644 index 00000000..db5dacab --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/servo.py @@ -0,0 +1,53 @@ +""" +Servo + +MicroPython library for the Servo(0~180°) +======================================================= + +#Preliminary composition 20220803 + +dahanzimin From the Mixly Team +""" +from machine import Pin,PWM + +class Servo: + __species = {} + __first_init = True + + def __new__(cls, pin, *args, **kwargs): + if pin not in cls.__species.keys(): + cls.__first_init = True + cls.__species[pin]=object.__new__(cls) + return cls.__species[pin] + + def __init__(self,pin): + if self.__first_init: + self.__first_init = False + self._pulse=None + self.pwm = PWM(Pin(pin), duty=0, freq=50) + + def servo_write(self,pulse): + self._pulse=pulse + self.pwm.duty_u16(int(1638.375 + 6553.5 * pulse)) + + def servo_read(self): + return self._pulse + +#-------Method usage of class-------- + +def servo180_angle(pin,angle=None): + if angle is None: + return int(Servo(pin).servo_read()*180) + else: + if not 0<= angle <= 180: + raise ValueError("The effective range of the servo(180) angle is 0~180°") + Servo(pin).servo_write(angle/180) + + +def servo360_speed(pin,speed=None): + if speed is None: + return int(Servo(pin).servo_read()*200-100) + else: + if not -100<= speed <= 100: + raise ValueError("The effective range of the servo(360) speed is -100~100%") + Servo(pin).servo_write((speed+100)/200) diff --git a/mixly/boards/default/micropython/build/lib/sht20.py b/mixly/boards/default/micropython/build/lib/sht20.py new file mode 100644 index 00000000..adc44a0d --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/sht20.py @@ -0,0 +1,37 @@ +from struct import unpack as unp +from time import sleep_ms + +# SHT20 default address +SHT20_I2CADDR = 64 +TRI_T_MEASURE_NO_HOLD = b'\xf3' +TRI_RH_MEASURE_NO_HOLD = b'\xf5' +READ_USER_REG = b'\xe7' +WRITE_USER_REG = b'\xe6' +SOFT_RESET = b'\xfe' + +class SHT20(object): + def __init__(self, i2c_bus): + self._address = SHT20_I2CADDR + self._bus = i2c_bus + + def get_SHT_temperature(self): + self._bus.writeto(self._address, TRI_T_MEASURE_NO_HOLD) + sleep_ms(150) + origin_data = self._bus.readfrom(self._address, 2) + origin_value = unp('>h', origin_data)[0] + value = -46.85 + 175.72 * (origin_value / 65536) + return value + + def get_SHT_relative_humidity(self): + self._bus.writeto(self._address, TRI_RH_MEASURE_NO_HOLD) + sleep_ms(150) + origin_data = self._bus.readfrom(self._address, 2) + origin_value = unp('>H', origin_data)[0] + value = -6 + 125 * (origin_value / 65536) + return value + + def humidity(self): + return self.get_SHT_relative_humidity() + + def temperature(self): + return self.get_SHT_temperature() diff --git a/mixly/boards/default/micropython/build/lib/shtc3.py b/mixly/boards/default/micropython/build/lib/shtc3.py new file mode 100644 index 00000000..eb2e45f7 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/shtc3.py @@ -0,0 +1,134 @@ +""" +SHTC3 + +MicroPython library for the SHTC3(Humidity and Temperature) +======================================================= + +#Preliminary composition 20220224 +#https://github.com/adafruit/Adafruit_CircuitPython_SHTC3.git + +dahanzimin From the Mixly Team +""" + +from time import sleep +from micropython import const +from struct import unpack_from + +_SHTC3_DEFAULT_ADDR = const(0x70) # SHTC3 I2C Address +_SHTC3_READID = const(0xEFC8) # Read Out of ID Register +_SHTC3_SOFTRESET = const(0x805D) # Soft Reset +_SHTC3_SLEEP = const(0xB098) # Enter sleep mode +_SHTC3_WAKEUP = const(0x3517) # Wakeup mode +_SHTC3_CHIP_ID = const(0x807) +_SHTC3_NORMAL_MEAS = const(0x7866) +_SHTC3_LOWPOW_MEAS = const(0x609C) + +class SHTC3: + def __init__(self, i2c_bus, addr = _SHTC3_DEFAULT_ADDR): + self._device= i2c_bus + self._address = addr + self._buffer = bytearray(6) + self.low_power = False + self.sleeping = False + self.reset() + if self._get_chip_id() != _SHTC3_CHIP_ID: + raise AttributeError("Cannot find a SHTC3") + + def _write_command(self, command): + """helper function to write a command to the i2c device""" + self._buffer[0] = command >> 8 + self._buffer[1] = command & 0xFF + self._device.writeto(self._address,self._buffer[0:2]) + + def _get_chip_id(self): # readCommand(SHTC3_READID, data, 3); + """Determines the chip id of the sensor""" + self._write_command(_SHTC3_READID) + sleep(0.001) + self._device.readfrom_into(self._address,self._buffer) + return unpack_from(">H", self._buffer)[0] & 0x083F + + def reset(self): + """Perform a soft reset of the sensor, resetting all settings to their power-on defaults""" + self.sleeping = False + try: + self._write_command(_SHTC3_SOFTRESET) + + except RuntimeError as run_err: + if run_err.args and run_err.args[0] != "I2C device address was NACK'd": + raise run_err + sleep(0.001) + + @property + def sleeping(self): + """Determines the sleep state of the sensor""" + return self._cached_sleep + + @sleeping.setter + def sleeping(self, sleep_enabled): + if sleep_enabled: + self._write_command(_SHTC3_SLEEP) + else: + self._write_command(_SHTC3_WAKEUP) + sleep(0.001) + self._cached_sleep = sleep_enabled + + @property + def low_power(self): + """Enables the less accurate low power mode, trading accuracy for power consumption""" + return self._low_power + + @low_power.setter + def low_power(self, low_power_enabled): + self._low_power = low_power_enabled + + @property + def measurements(self): + """both `temperature` and `relative_humidity`, read simultaneously""" + self.sleeping = False + temperature = None + humidity = None + if self.low_power: + self._write_command(_SHTC3_LOWPOW_MEAS) + sleep(0.001) + else: + self._write_command(_SHTC3_NORMAL_MEAS) + sleep(0.013) + + self._device.readfrom_into(self._address,self._buffer) + + temp_data = self._buffer[0:2] + temp_crc = self._buffer[2] + humidity_data = self._buffer[3:5] + humidity_crc = self._buffer[5] + + if temp_crc != self._crc8(temp_data) or humidity_crc != self._crc8(humidity_data): + return + + raw_temp = unpack_from(">H", temp_data)[0] + raw_temp = ((4375 * raw_temp) >> 14) - 4500 + temperature = raw_temp / 100.0 + raw_humidity = unpack_from(">H", humidity_data)[0] + raw_humidity = (625 * raw_humidity) >> 12 + humidity = raw_humidity / 100.0 + + self.sleeping = True + return (temperature, humidity) + + @staticmethod + def _crc8(buffer): + """verify the crc8 checksum""" + crc = 0xFF + for byte in buffer: + crc ^= byte + for _ in range(8): + if crc & 0x80: + crc = (crc << 1) ^ 0x31 + else: + crc = crc << 1 + return crc & 0xFF # return the bottom 8 bits + + def humidity(self): + return self.measurements[1] + + def temperature(self): + return self.measurements[0] diff --git a/mixly/boards/default/micropython/build/lib/sonar.py b/mixly/boards/default/micropython/build/lib/sonar.py new file mode 100644 index 00000000..6b8e6ba4 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/sonar.py @@ -0,0 +1,39 @@ +""" +CS100/HC-SR04 + +Micropython library for the CS100/HC-SR04(Ultrasonic ranging) +======================================================= +@dahanzimin From the Mixly Team +""" +from time import sleep_us +from machine import Pin, time_pulse_us + +class Sonar: + __species = {} + __first_init = True + + def __new__(cls, trig, echo, *args, **kwargs): + if (trig, echo) not in cls.__species.keys(): + cls.__first_init = True + cls.__species[(trig, echo) ] = object.__new__(cls) + return cls.__species[(trig, echo)] + + def __init__(self, trig, echo, max_rang=400): + if self.__first_init: + self.__first_init = False + self.trig = Pin(trig, Pin.OUT, value=0) + self.echo = Pin(echo, Pin.IN) + self.timeout_us = int(max_rang * 2 * 29.1) + + def checkdist(self): + self.trig.value(0) + sleep_us(5) + self.trig.value(1) + sleep_us(10) + self.trig.value(0) + try: + pulse_time = time_pulse_us(self.echo, 1, self.timeout_us) + pulse_time = pulse_time if pulse_time >= 0 else self.timeout_us + return round(pulse_time / 2 / 29.1, 2) # 1cm each 29.1us + except: + return None diff --git a/mixly/boards/default/micropython/build/lib/spl06_001.py b/mixly/boards/default/micropython/build/lib/spl06_001.py new file mode 100644 index 00000000..c291c0a6 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/spl06_001.py @@ -0,0 +1,115 @@ +""" +_SPL06-001 + +MicroPython library for the _SPL06-001(Air pressure sensor) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_SPL06_ADDRESS = const(0x77) +_SPL06_REG_PSR = const(0x00) +_SPL06_REG_TMP = const(0x03) +_SPL06_PSR_CFG = const(0x06) +_SPL06_TMP_CFG = const(0x07) +_SPL06_MEAS_CFG = const(0x08) +_SPL06_CFG_REG = const(0x09) +_SPL06_REG_RST = const(0x0C) +_SPL06_REG_ID = const(0x0D) +_SPL06_REG_COEF = const(0x10) + +#Parameter selection(sample/sec, times, kT/kP) +_SPL06_PSR_TMP_1 = (0<<4, 0, 524288) +_SPL06_PSR_TMP_2 = (1<<4, 1, 1572864) +_SPL06_PSR_TMP_4 = (2<<4, 2, 3670016) +_SPL06_PSR_TMP_8 = (3<<4, 3, 7864320) +_SPL06_PSR_TMP_16 = (4<<4, 4, 253952) +_SPL06_PSR_TMP_32 = (5<<4, 5, 516096) +_SPL06_PSR_TMP_64 = (6<<4, 6, 1040384) +_SPL06_PSR_TMP_128 = (7<<4, 7, 2088960) + +class SPL06: + def __init__(self, i2c_bus, addr=_SPL06_ADDRESS, rate=_SPL06_PSR_TMP_32): + self._device = i2c_bus + self._address = addr + self._rate = rate + self._psr = 0 + self._tmp = 0 + self._alt = 0 + if self._rreg(_SPL06_REG_ID) != 0x10: + raise AttributeError("Cannot find a SPL06-001") + self._init() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _u2s(self, value, n=8): + return value if value < (1 << (n-1)) else value - (1 << n) + + def _status(self): + '''数据转换状态''' + status = self._rreg(_SPL06_MEAS_CFG) + return status & 0x80, status & 0x40, (status >> 4 & 0x01) & (status >> 5 & 0x01) #COEF_RDY,SENSOR_RDY,TMP_RDY+PRS_RDY + + def _init(self): + '''软复位''' + self._wreg(_SPL06_REG_RST, 0x89) + time.sleep_ms(50) + '''判断校准数据是否就绪,并读取''' + while not self._status()[0]: + time.sleep_ms(1) + buf = self._rreg(_SPL06_REG_COEF, 18) + self._c0 = self._u2s(buf[0] << 4 | buf[1] >> 4, 12) + self._c1 = self._u2s((buf[1] & 0x0F) << 8 | buf[2], 12) + self._c00 = self._u2s(buf[3] << 12 | buf[4] << 4 | buf[5] >> 4, 20) + self._c10 = self._u2s((buf[5] & 0x0F) << 16 | buf[6] << 8 | buf[7], 20) + self._c01 = self._u2s(buf[8] << 8 | buf[9], 16) + self._c11 = self._u2s(buf[10] << 8 | buf[11], 16) + self._c20 = self._u2s(buf[12] << 8 | buf[13], 16) + self._c21 = self._u2s(buf[14] << 8 | buf[15], 16) + self._c30 = self._u2s(buf[16] << 8 | buf[17], 16) + + '''判断传感器是否就绪,并设置''' + while not self._status()[1]: + time.sleep_ms(1) + self._wreg(_SPL06_MEAS_CFG, 0x07) #Continuous pressure and temperature + self._wreg(_SPL06_PSR_CFG, self._rate[0] | self._rate[1]) #Configuration of pressure measurement. + self._wreg(_SPL06_TMP_CFG, self._rate[0] | self._rate[1] | 0x80) #Configuration of temperature measurement. + self._rreg(_SPL06_REG_PSR, 6) + + if self._rate[1] > 3: + self._wreg(_SPL06_CFG_REG, self._rreg(_SPL06_CFG_REG) | 0x0C) #when the oversampling rate is >8 times. + + ''''判断数据是否就绪,并读取''' + #while not self._status()[2]: + #time.sleep_ms(1) #数据就绪需要耗时1s左右 + + @property + def getdata(self): + '''处理获取数据''' + if self._status()[2]: + buf = self._rreg(_SPL06_REG_PSR, 6) + praw = self._u2s(buf[0] << 16 | buf[1] << 8 | buf[2], 24) / self._rate[2] + traw = self._u2s(buf[3] << 16 | buf[4] << 8 | buf[5], 24) / self._rate[2] + try: + self._psr = self._c00 + praw * (self._c10 + praw *(self._c20 + praw * self._c30)) + traw * self._c01 + traw * praw * (self._c11 + praw * self._c21) + except: + self._psr = 0 + self._tmp = self._c0 * 0.5 + self._c1 * traw + self._alt = (1 - (self._psr / 101325) ** (1/5.255)) * 44330 + return round(self._psr/100, 2), round(self._tmp, 2), round(self._alt,2) + + def pressure(self): + return self.getdata[0] + + def temperature(self): + return self.getdata[1] + + def altitude(self, reference=1013.25): + return round((pow((reference / 33.8639), 0.190255) - pow((self.getdata[0] / 33.8639), 0.190255)) / 0.000013125214, 2) diff --git a/mixly/boards/default/micropython/build/lib/ssd1106.py b/mixly/boards/default/micropython/build/lib/ssd1106.py new file mode 100644 index 00000000..a4d2e810 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ssd1106.py @@ -0,0 +1,124 @@ +""" +SSD1106 + +library for the SSD1x06 OLED128x64 +======================================================= +@dahanzimin From the Mixly Team +""" +import uframebuf +from micropython import const + +SET_CONTRAST = const(0x81) +SET_ENTIRE_ON = const(0xa4) +SET_NORM_INV = const(0xa6) +SET_DISP_OFF = const(0xae) +SET_DISP_ON = const(0xaf) +SET_MEM_ADDR = const(0x20) +SET_PAGE_ADDR = const(0x22) +SET_DISP_START_LINE = const(0x40) +SET_SEG_REMAP = const(0xa0) +SET_MUX_RATIO = const(0xa8) +SET_COM_OUT_DIR = const(0xc0) +SET_DISP_OFFSET = const(0xd3) +SET_COM_PIN_CFG = const(0xda) +SET_DISP_CLK_DIV = const(0xd5) +SET_PRECHARGE = const(0xd9) +SET_VCOM_DESEL = const(0xdb) +SET_CHARGE_PUMP = const(0x8d) +SET_COL_ADDR_L = const(0x02) +SET_COL_ADDR_H = const(0x10) +SET_PAGE_ADDR1 = const(0xb0) +SET_CONTRACT_CTRL = const(0x81) + +class SSD1106(uframebuf.FrameBuffer_Uincode): + def __init__(self, width, height, external_vcc, l_offset=0, h_offset=0): + self._external = external_vcc + self._l_offset = l_offset + self._h_offset = h_offset + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_VLSB) + self.init_display() + + def init_display(self): + for cmd in ( + SET_DISP_OFF, # display off + SET_DISP_CLK_DIV, 0x80, # timing and driving scheme + SET_MUX_RATIO, 0x3f, #0xa8 + SET_DISP_OFFSET, 0x00, #0xd3 + SET_DISP_START_LINE | 0x00, #start line + SET_CHARGE_PUMP, 0x10 if self._external else 0x14, + SET_MEM_ADDR, 0x00, # address setting + SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 + SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 + SET_COM_PIN_CFG, 0x12, + SET_CONTRACT_CTRL, 0xcf, + SET_PRECHARGE, 0x22 if self._external else 0xf1, + SET_VCOM_DESEL, 0x40, # 0.83*Vcc + SET_ENTIRE_ON, # output follows RAM contents + SET_NORM_INV, + SET_DISP_ON): # on + self.write_cmd(cmd) + self.fill(0) + self.show() + + def poweroff(self): + self.write_cmd(SET_DISP_OFF) + + def poweron(self): + self.write_cmd(SET_DISP_ON) + + def contrast(self, contrast): + self.write_cmd(SET_CONTRAST) + self.write_cmd(contrast) + + def invert(self, invert): + self.write_cmd(SET_NORM_INV | (invert & 1)) + + def show(self): + for i in range(0, 8): + self.write_cmd(SET_PAGE_ADDR1 + i) + self.write_cmd(SET_COL_ADDR_L + self._l_offset) + self.write_cmd(SET_COL_ADDR_H + self._h_offset) + self.write_data(self._buffer[i * 128:(i + 1) * 128]) #send one page display data + +class SSD1106_I2C(SSD1106): + def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False, l_offset=0, h_offset=0): + self.i2c = i2c + self.addr = addr + self.temp = bytearray(2) + super().__init__(width, height, external_vcc, l_offset, h_offset) + + def write_cmd(self, cmd): + self.temp[0] = 0x80 + self.temp[1] = cmd + self.i2c.writeto(self.addr, self.temp) + + def write_data(self, buf): + tmp = bytearray([0x40]) + self.i2c.writeto(self.addr, tmp+buf) + +class SSD1106_SPI(SSD1106): + def __init__(self, width, height, spi, dc, cs, external_vcc=False, l_offset=0, h_offset=0): + self.rate = 10 * 1024 * 1024 + dc.init(dc.OUT, value=0) + cs.init(cs.OUT, value=1) + self.spi = spi + self.dc = dc + self.cs = cs + super().__init__(width, height, external_vcc, l_offset, h_offset) + + def write_cmd(self, cmd): + self.spi.init(baudrate=self.rate, polarity=0, phase=0) + self.cs(1) + self.dc(0) + self.cs(0) + self.spi.write(bytearray([cmd])) + self.cs(1) + + def write_data(self, buf): + self.spi.init(baudrate=self.rate, polarity=0, phase=0) + self.cs(1) + self.dc(1) + self.cs(0) + self.spi.write(buf) + self.cs(1) diff --git a/mixly/boards/default/micropython/build/lib/st7735.py b/mixly/boards/default/micropython/build/lib/st7735.py new file mode 100644 index 00000000..557b38f7 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/st7735.py @@ -0,0 +1,117 @@ +""" +ST7735 + +MicroPython library for the ST7735(TFT-SPI) +======================================================= +#Preliminary composition 20230822 + +@dahanzimin From the Mixly Team +""" +import time, uframebuf +from machine import Pin, PWM +from micropython import const + +_CMD_SWRESET = const(0x01) +_CMD_SLPOUT = const(0x11) +_CMD_PTLON = const(0x12) +_CMD_NORON = const(0x13) +_CMD_INVOFF = const(0x20) +_CMD_INVON = const(0x21) +_CMD_DISPOFF = const(0x28) +_CMD_DISPON = const(0x29) +_CMD_CASET = const(0x2A) +_CMD_RASET = const(0x2B) +_CMD_RAMWR = const(0x2C) +_CMD_RAMRD = const(0x2E) +_CMD_PTLAR = const(0x30) +_CMD_COLMOD = const(0x3A) +_CMD_MADCTL = const(0x36) +_CMD_FRMCTR1 = const(0xB1) +_CMD_FRMCTR2 = const(0xB2) +_CMD_FRMCTR3 = const(0xB3) +_CMD_INVCTR = const(0xB4) +_CMD_PWCTR1 = const(0xC0) +_CMD_PWCTR2 = const(0xC1) +_CMD_PWCTR3 = const(0xC2) +_CMD_PWCTR4 = const(0xC3) +_CMD_PWCTR5 = const(0xC4) +_CMD_VMCTR1 = const(0xC5) +_CMD_GMCTRP1 = const(0xE0) +_CMD_GMCTRN1 = const(0xE1) + +class ST7735(uframebuf.FrameBuffer_Uincode): + def __init__(self, spi, width, height, dc_pin=None, cs_pin=None, bl_pin=None, font_address=0x700000, rotation=0): + self.spi = spi + self.dc = Pin(dc_pin, Pin.OUT, value=1) + self.cs = Pin(cs_pin, Pin.OUT, value=1) + self._buffer = bytearray(width * height * 2) + super().__init__(self._buffer, width, height, uframebuf.RGB565) + self.font(font_address) + self._init() + self.rotation(rotation) + self.fill(0) + self.show() + time.sleep_ms(100) + self._brightness = 0.6 + self.bl_led = PWM(Pin(bl_pin), duty_u16=int(self._brightness * 60000)) if bl_pin else None + + def _write(self, cmd, dat = None): + self.cs.off() + self.dc.off() + self.spi.write(bytearray([cmd])) + self.cs.on() + if dat is not None: + self.cs.off() + self.dc.on() + self.spi.write(dat) + self.cs.on() + + def _init(self): + """Display initialization configuration""" + for cmd, data, delay in [ + (_CMD_SWRESET, None, 100), + (_CMD_SLPOUT, None, 200), + (_CMD_FRMCTR1, b'\x01\x2c\x2d', 10), + (_CMD_FRMCTR2, b'\x01\x2c\x2d', 10), + (_CMD_FRMCTR3, b'\x01\x2c\x2d', 10), + (_CMD_INVCTR, b'\x07', None), + (_CMD_PWCTR1, b'\xa2\x02\x84', 10), + (_CMD_PWCTR2, b'\xc5', None), + (_CMD_PWCTR3, b'\x0a\x00', None), + (_CMD_PWCTR4, b'\x8a\x2a', None), + (_CMD_PWCTR5, b'\x8a\xee', None), + (_CMD_VMCTR1, b'\x0e', None), + (_CMD_GMCTRP1, b'\x02\x1c\x07\x12\x37\x32\x29\x2d\x29\x25\x2b\x39\x00\x01\x03\x10', None), + (_CMD_GMCTRN1, b'\x03\x1d\x07\x06\x2e\x2c\x29\x2d\x2e\x2e\x37\x3f\x00\x00\x02\x10', None), + (_CMD_COLMOD, b'\x05', 10), + (_CMD_NORON, None, 10), + (_CMD_DISPON, None, 200), + ]: + self._write(cmd, data) + if delay: + time.sleep_us(delay) + + def rotation(self, rotation): + self._write(_CMD_MADCTL, b'\x60') if rotation else self._write(_CMD_MADCTL, b'\xa0') + self._write(_CMD_CASET, b'\x01\x01\x01\xa0') + self._write(_CMD_RASET, b'\x02\x02\x02\x81') + + def get_brightness(self): + return self._brightness + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0~1.0") + self._brightness = brightness + self.bl_led.duty_u16(int(brightness*60000)) + + def color(self, red, green=None, blue=None): + """ Convert red, green and blue values (0-255) into a 16-bit 565 encoding.""" + if green is None or blue is None: + return red + else: + return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3 + + def show(self): + """Refresh the display and show the changes.""" + self._write(_CMD_RAMWR, self._buffer) diff --git a/mixly/boards/default/micropython/build/lib/st7789.py b/mixly/boards/default/micropython/build/lib/st7789.py new file mode 100644 index 00000000..638c9255 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/st7789.py @@ -0,0 +1,330 @@ +""" +ST7789 + +MicroPython library for the ST7789(TFT-SPI) +======================================================= +#Preliminary composition 20220830 +#https://github.com/russhughes/st7789py_mpy + +dahanzimin From the Mixly Team +""" + +import time +from machine import Pin +from micropython import const +from uframebuf import Font_Uincode, Image +import ustruct as struct + + +ST7789_NOP = const(0x00) +ST7789_SWRESET = const(0x01) +ST7789_RDDID = const(0x04) +ST7789_RDDST = const(0x09) +ST7789_SLPIN = const(0x10) +ST7789_SLPOUT = const(0x11) +ST7789_PTLON = const(0x12) +ST7789_NORON = const(0x13) +ST7789_INVOFF = const(0x20) +ST7789_INVON = const(0x21) +ST7789_DISPOFF = const(0x28) +ST7789_DISPON = const(0x29) +ST7789_CASET = const(0x2A) +ST7789_RASET = const(0x2B) +ST7789_RAMWR = const(0x2C) +ST7789_RAMRD = const(0x2E) +ST7789_PTLAR = const(0x30) +ST7789_VSCRDEF = const(0x33) +ST7789_COLMOD = const(0x3A) +ST7789_MADCTL = const(0x36) +ST7789_VSCSAD = const(0x37) +ST7789_MADCTL_MY = const(0x80) +ST7789_MADCTL_MX = const(0x40) +ST7789_MADCTL_MV = const(0x20) +ST7789_MADCTL_ML = const(0x10) +ST7789_MADCTL_BGR = const(0x08) +ST7789_MADCTL_MH = const(0x04) +ST7789_MADCTL_RGB = const(0x00) +ST7789_RDID1 = const(0xDA) +ST7789_RDID2 = const(0xDB) +ST7789_RDID3 = const(0xDC) +ST7789_RDID4 = const(0xDD) +COLOR_MODE_65K = const(0x50) +COLOR_MODE_262K = const(0x60) +COLOR_MODE_12BIT = const(0x03) +COLOR_MODE_16BIT = const(0x05) +COLOR_MODE_18BIT = const(0x06) +COLOR_MODE_16M = const(0x07) + +# Color definitions +BLACK = const(0x0000) +BLUE = const(0x001F) +RED = const(0xF800) +GREEN = const(0x07E0) +CYAN = const(0x07FF) +MAGENTA = const(0xF81F) +YELLOW = const(0xFFE0) +WHITE = const(0xFFFF) + +_BUFFER_SIZE = const(256) + +# Rotation tables (width, height, xstart, ystart)[rotation % 4] +WIDTH_320 = [(240, 320, 0, 0),(320, 240, 0, 0),(240, 320, 0, 0),(320, 240, 0, 0)] +WIDTH_240 = [(240, 240, 0, 0),(240, 240, 0, 0),(240, 240, 0, 80),(240, 240, 80, 0)] +WIDTH_135 = [(135, 240, 52, 40),(240, 135, 40, 53),(135, 240, 53, 40),(240, 135, 40, 52)] + +ROTATIONS = [0x00, 0x60, 0xc0, 0xa0] + +def color565(red, green=0, blue=0): + """ Convert red, green and blue values (0-255) into a 16-bit 565 encoding.""" + try: + red, green, blue = red # see if the first var is a tuple/list + except TypeError: + pass + return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3 + +def _encode_pos(x, y): + """Encode a postion into bytes.""" + return struct.pack(">HH", x, y) + +def _encode_pixel(color): + """Encode a pixel color into bytes.""" + return struct.pack(">H", color) + +class ST7789(): + def __init__(self, spi, width, height, dc_pin=None,cs_pin=None, rotation=0, font_address=0x700000): + if height != 240 or width not in [320, 240, 135]: + raise ValueError("Unsupported display. 320x240, 240x240 and 135x240 are supported.") + + self._font= Font_Uincode(font_address) + self._image= Image() + self._display_width = self.width = width + self._display_height = self.height = height + self.xstart = 0 + self.ystart = 0 + self.spi = spi + self.spi.init(polarity=1) + self.dc = Pin(dc_pin, Pin.OUT) + self.cs = Pin(cs_pin, Pin.OUT) + self._rotation = rotation % 4 + self.soft_reset() + self.sleep_mode(False) + + self._set_color_mode(COLOR_MODE_65K | COLOR_MODE_16BIT) + time.sleep_ms(50) + self.rotation(self._rotation) + self.inversion_mode(True) + time.sleep_ms(10) + self._write(ST7789_NORON) + time.sleep_ms(10) + self.fill(0) + self._write(ST7789_DISPON) + time.sleep_ms(500) + + def _write(self, command=None, data=None): + """SPI write to the device: commands and data.""" + if self.cs: + self.cs.off() + if command is not None: + self.dc.off() + self.spi.write(bytes([command])) + if data is not None: + self.dc.on() + self.spi.write(data) + if self.cs: + self.cs.on() + + def soft_reset(self): + """Soft reset display.""" + self._write(ST7789_SWRESET) + time.sleep_ms(150) + + def sleep_mode(self, value): + """Enable or disable display sleep mode.""" + if value: + self._write(ST7789_SLPIN) + else: + self._write(ST7789_SLPOUT) + + def inversion_mode(self, value): + """Enable or disable display inversion mode.""" + if value: + self._write(ST7789_INVON) + else: + self._write(ST7789_INVOFF) + + def _set_color_mode(self, mode): + """ Set display color mode. """ + self._write(ST7789_COLMOD, bytes([mode & 0x77])) + + def rotation(self, rotation): + """Set display rotation.""" + rotation %= 4 + self._rotation = rotation + madctl = ROTATIONS[rotation] + + if self._display_width == 320: + table = WIDTH_320 + elif self._display_width == 240: + table = WIDTH_240 + elif self._display_width == 135: + table = WIDTH_135 + else: + raise ValueError("Unsupported display. 320x240, 240x240 and 135x240 are supported.") + self.width, self.height, self.xstart, self.ystart = table[rotation] + self._write(ST7789_MADCTL, bytes([madctl])) + + def _set_columns(self, start, end): + """Send CASET (column address set) command to display.""" + if start <= end <= self.width: + self._write(ST7789_CASET, _encode_pos( + start+self.xstart, end + self.xstart)) + + def _set_rows(self, start, end): + """Send RASET (row address set) command to display.""" + if start <= end <= self.height: + self._write(ST7789_RASET, _encode_pos( + start+self.ystart, end+self.ystart)) + + def _set_window(self, x0, y0, x1, y1): + """Set window to column and row address.""" + self._set_columns(x0, x1) + self._set_rows(y0, y1) + self._write(ST7789_RAMWR) + + def vline(self, x, y, length, color): + """Draw vertical line at the given location and color.""" + self.fill_rect(x, y, 1, length, color) + + def hline(self, x, y, length, color): + """Draw horizontal line at the given location and color.""" + self.fill_rect(x, y, length, 1, color) + + def pixel(self, x, y, color): + """Draw a pixel at the given location and color.""" + self._set_window(x, y, x, y) + pixel_color =_encode_pixel(color) if type(color)==int else _encode_pixel(color565(color)) + self._write(None, pixel_color) + + def blit_buffer(self, buffer, x, y, width, height): + """Copy buffer to display at the given location.""" + self._set_window(x, y, x + width - 1, y + height - 1) + self._write(None, buffer) + + def rect(self, x, y, w, h, color): + """Draw a rectangle at the given location, size and color.""" + self.hline(x, y, w, color) + self.vline(x, y, h, color) + self.vline(x + w - 1, y, h, color) + self.hline(x, y + h - 1, w, color) + + def fill_rect(self, x, y, width, height, color): + """Draw a rectangle at the given location, size and filled with color.""" + self._set_window(x, y, x + width - 1, y + height - 1) + chunks, rest = divmod(width * height, _BUFFER_SIZE) + pixel = _encode_pixel(color) if type(color)==int else _encode_pixel(color565(color)) + self.dc.on() + if chunks: + data = pixel * _BUFFER_SIZE + for _ in range(chunks): + self._write(None, data) + if rest: + self._write(None, pixel * rest) + + def fill(self, color): + """Fill the entire FrameBuffer with the specified color.""" + self.fill_rect(0, 0, self.width, self.height, color) + + def line(self, x0, y0, x1, y1, color): + """Draw a single pixel wide line starting at x0, y0 and ending at x1, y1.""" + steep = abs(y1 - y0) > abs(x1 - x0) + if steep: + x0, y0 = y0, x0 + x1, y1 = y1, x1 + if x0 > x1: + x0, x1 = x1, x0 + y0, y1 = y1, y0 + dx = x1 - x0 + dy = abs(y1 - y0) + err = dx // 2 + ystep = 1 if y0 < y1 else -1 + while x0 <= x1: + if steep: + self.pixel(y0, x0, color) + else: + self.pixel(x0, y0, color) + err -= dy + if err < 0: + y0 += ystep + err += dx + x0 += 1 + + def image(self,path, x=0, y=0, size=1, color=WHITE, invert=0): + """Set buffer to value of Python Imaging Library image""" + size=max(round(size),1) + if type(path) ==str : + buffer_info,(width, height) = self._image.load(path,invert) + elif type(path) ==bytes: + buffer_info,(width, height) = self._image.load_py(path,invert) + else: + raise ValueError("invalid input") + + self.bitmap((buffer_info,(width, height)), x, y, size, color) + + def bitmap(self,buffer, x=0, y=0, size=1, color=WHITE): + """Graphic model display(buffer,(width,height))""" + buffer_info,(width,height)=buffer + if x < -width*size or x >= self.width or y < -height*size or y >= self.height: + return #Limit reasonable display area + color_buffer = bytearray(0) + byteWidth = int((width + 7) / 8) + for j in range(height): + for i in range(width): + if buffer_info[int(j * byteWidth + i / 8)] & (0x80 >> (i & 7)): + self.fill_rect(x+i*size, y+j*size, size, size, color) + + def _take_buffer(self,strs,space,size=1): + '''Get character lattice information first''' + font_buffer=[] + font_len=0 + for c in strs: + buffer=self._font.chardata(c) + font_buffer.append(buffer) + font_len=font_len+buffer[1][0]*size+space + return font_len,font_buffer + + def shows(self,data,x=0,y=0,size=1,space=0,center=False, color=WHITE): + """Display character""" + if data: + size=max(round(size),1) + font_len,font_buffer=self._take_buffer(str(data),space,size) + x=(self.width-font_len+space)//2 if center else x + #self.fill_rect(x-1,y-1,font_len+2,font_buffer[0][1][1]*size+2,0) + for buffer in font_buffer: #Display character + self.bitmap(buffer,x,y,size,color) + x=buffer[1][0]*size+x+space + + def frame(self, data, delay=500, size=5, color=WHITE): + """Display one frame per character""" + if data: + size=max(round(size),1) + _,font_buffer=self._take_buffer(str(data),0) + for buffer in font_buffer: + x=(self.width - buffer[1][0]*size)//2 + y=(self.height - buffer[1][1]*size)//2 + self.fill_rect(x-1,y-1,buffer[1][0]*size+2,buffer[1][1]*size+2,0) + self.bitmap(buffer,x,y,size,color) + #self.show() + time.sleep_ms(delay) + + def scroll(self, data, y=0, size=1, space=0, speed=5, color=WHITE): + """Scrolling characters""" + if data: + size=max(round(size),1) + font_len,font_buffer=self._take_buffer(str(data),space,size) + for i in range(font_len-space+self.width): + x=-i+self.width + self.fill_rect(x-1,y-1,self.width-x+2,font_buffer[0][1][1]*size+2,0) + for buffer in font_buffer: + self.bitmap(buffer,x,y,size,color) + x=buffer[1][0]*size+x+space + time.sleep_ms(speed) diff --git a/mixly/boards/default/micropython/build/lib/syn6288.py b/mixly/boards/default/micropython/build/lib/syn6288.py new file mode 100644 index 00000000..55763cc6 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/syn6288.py @@ -0,0 +1,83 @@ +""" +SYN6288 + +Micropython library for the SYN6288(speech synthesis) +======================================================= +#Preliminary composition 20220805 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +REG_PLAY_SST = const(0x01) +#REG_BAUD_SST = const(0x31) +#REG_STOP_SST = const(0x02) +#REG_PAUSE_SST = const(0x03) +#REG_RESUME_SST = const(0x04) +#EG_QUERY_SST = const(0x21) +#EG_DOWN_SST = const(0x88) + +class SYN6288: + def __init__(self, uart): + self._uart=uart + self._uart.init(baudrate=9600) + self._state=False + self._volume="[v10]" + + def _wreg(self, reg, val5=0,val3=None, data=None): + '''Write memory address''' + buffer=[0xFD,0x00,0x00,reg] + eec=0 + + if not val5 is None and not val3 is None : + buffer.append((val3 & 0x07) | (val5 << 3)) + if not data is None: + for char in data: + buffer.append(ord(char) >> 8) + buffer.append(ord(char) & 0xFF) + + buffer[2]= len(buffer)-2 + for i in range(len(buffer)): + eec^=int(buffer[i]) + buffer.append(eec) + + self._uart.write(bytes(buffer)) + + def volume(self,vol=None): + if vol is None: + return int(self._volume[2:-1]) + if not 0 <= vol <= 16: + raise ValueError("The effective range of volume value is 0~16") + else: + self._volume="[v{}]".format(vol) + + def synthesis(self, data, music=0, blocking=True): + """Support uincode coded speech synthesis""" + self._wreg(REG_PLAY_SST,music,3,self._volume+str(data)) + time.sleep(0.1) + while blocking : + if not self.status(): + break + + def status(self): + """Playback status (true is playing)""" + if self._uart.any(): + state= self._uart.read() + if state==b'A': + self._state = True + if state==b'O': + self._state = False + return self._state + + def hint_tones(self,number, blocking=True): + """Play built-in prompt tone""" + if number <25: + tones="sound"+chr(ord("a")+number) + elif number <33: + tones="msg"+chr(ord("a")+number-25) + elif number <48: + tones="ring"+chr(ord("a")+number-33) + else: + raise ValueError("Input out of range") + self.synthesis(tones,blocking=blocking) diff --git a/mixly/boards/default/micropython/build/lib/tiny_webdb.py b/mixly/boards/default/micropython/build/lib/tiny_webdb.py new file mode 100644 index 00000000..7ff1fde1 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/tiny_webdb.py @@ -0,0 +1,91 @@ +import urequests as requests + + +def url_quote(s): + safe = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-" + s = str(s) + res = bytearray() + for b in s.encode('utf-8'): + if b in safe: + res.append(b) + else: + res.extend(b'%' + b'%02X' % b) + return res.decode() + + +class TinyWebDB: + def __init__(self, *args): + if len(args) == 1: + self.init_with_mqtt(*args) + else: + self.init_with_user(*args) + + def init_with_user(self, url, username, password): + self._api_url = "" + self._username = username + self._password = password + self.set_url(url) + + def init_with_mqtt(self, mqtt_client): + self._api_url = "" + url, username, password = mqtt_client.get_server_info() + self.set_url('https://{}/tinydb'.format(url)) + self._username = username + self._password = password + + def update(self, key, value): + key = url_quote(str(key)) + value = url_quote(str(value)) + result = self._request("update", "tag={}&value={}".format(key, value)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + + def get(self, key): + key = url_quote(str(key)) + result = self._request("get", "tag={}".format(key)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + return result["value"] + + def count(self): + result = self._request("count") + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + return int(result["count"]) + + def search(self, no=1, count=1, tag='', dtype='both'): + no = str(no) + count = str(count) + tag = url_quote(tag) + result = self._request("search", "no={}&count={}&tag={}&type={}".format(no, count, tag, dtype)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + return result["data"] + + def delete(self, key): + key = url_quote(str(key)) + result = self._request("delete", "tag={}".format(key)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + + def set_url(self, url): + if url[-1] != '/': + url += '/' + self._api_url = url + + def _request(self, op, param=""): + data = "user={}&secret={}&action={}".format(self._username, self._password, op) + if param: + data += '&' + param + try: + headers = { + "Content-Type": "application/x-www-form-urlencoded" + } + response = requests.post(self._api_url, data=data, headers=headers) + result = {} + if response.status_code == 200: + result = response.json() + response.close() + return result + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected", e) diff --git a/mixly/boards/default/micropython/build/lib/tm1637.py b/mixly/boards/default/micropython/build/lib/tm1637.py new file mode 100644 index 00000000..287db069 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/tm1637.py @@ -0,0 +1,121 @@ +""" +TM1637 for Four Digit LED Display + +Micropython library for the TM1637 +======================================================= +@dahanzimin From the Mixly Team +""" +from machine import Pin +from time import sleep_us +from micropython import const + +TM1637_CMD1 = const(0x40) +TM1637_CMD2 = const(0xC0) +TM1637_CMD3 = const(0x80) +TM1637_DSP_ON = const(0x08) +TM1637_DELAY = const(0x0A) +_SEGMENTS = b'\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F\x77\x7C\x39\x5E\x79\x71' + +class TM1637: + def __init__(self, clk, dio, brightness=2): + self.clk = Pin(clk, Pin.OUT, value=0) + self.dio = Pin(dio, Pin.OUT, value=0) + sleep_us(TM1637_DELAY) + self._intensity = brightness + self.dbuf = [0, 0, 0, 0] + self.on() + + def _start(self): + self.dio(0) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + + def _stop(self): + self.dio(0) + sleep_us(TM1637_DELAY) + self.clk(1) + sleep_us(TM1637_DELAY) + self.dio(1) + + def _write(self, b): + for i in range(8): + self.dio((b >> i) & 1) + sleep_us(TM1637_DELAY) + self.clk(1) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + self.clk(1) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + + def intensity(self, val=None): + """Set the display brightness 0-7.""" + if val is None: + return self._intensity + val = max(min(val, 7), 0) + self._intensity = val + if val == 0: + self.off() + else: + self.on() + + def on(self): + self._start() + self._write(TM1637_CMD1) + self._stop() + self._start() + self._write(TM1637_CMD3 | TM1637_DSP_ON | self._intensity) + self._stop() + + def off(self): + self._start() + self._write(TM1637_CMD3) + self._stop() + + def dat(self, bit, data): + self._start() + self._write(TM1637_CMD2 | bit) + self._write(data) + self._stop() + + def clear(self): + self.dat(0, 0) + self.dat(1, 0) + self.dat(2, 0) + self.dat(3, 0) + self.dbuf = [0, 0, 0, 0] + + def showbit(self, num, bit=0): + self.dbuf[bit % 4] = _SEGMENTS[num % 16] + self.dat(bit, _SEGMENTS[num % 16]) + + def shownum(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num // 1000) % 10) + self.showbit(num % 10, 3) + self.showbit((num // 10) % 10, 2) + self.showbit((num // 100) % 10, 1) + + def showhex(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num >> 12) % 16) + self.showbit(num % 16, 3) + self.showbit((num >> 4) % 16, 2) + self.showbit((num >> 8) % 16, 1) + + def showDP(self, bit=1, show=True): + if show: + self.dat(bit, self.dbuf[bit] | 0x80) + else: + self.dat(bit, self.dbuf[bit] & 0x7F) diff --git a/mixly/boards/default/micropython/build/lib/tm1650.py b/mixly/boards/default/micropython/build/lib/tm1650.py new file mode 100644 index 00000000..23acc7b4 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/tm1650.py @@ -0,0 +1,83 @@ +""" +TM1650 for Four Digit LED Display + +Micropython library for the TM1650 +======================================================= +@dahanzimin From the Mixly Team +""" +from micropython import const +from machine import Pin, SoftI2C + +TM1650_CMD = const(0x24) +TM1650_DSP = const(0x34) +_SEGMENTS = b'\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F\x77\x7C\x39\x5E\x79\x71' + +class TM1650: + def __init__(self, i2c_bus=None, clk=0, dio=1, brightness=2): + if i2c_bus is None: + self.i2c = SoftI2C(scl=Pin(clk), sda=Pin(dio), freq=100000) + else: + self.i2c = i2c_bus + self._intensity = brightness + self.dbuf = [0, 0, 0, 0] + self.on() + + def _wreg(self, val): + self.i2c.writeto(TM1650_CMD, val.to_bytes(1, 'little')) + + def intensity(self, val=None): + """Set the display brightness 0-7.""" + if val is None: + return self._intensity + val = max(min(val, 7), 0) + self._intensity = val + if val == 0: + self.off() + else: + self.on() + + def on(self): + self._wreg((self._intensity << 4) | 0x01) + + def off(self): + self._wreg(0) + + def dat(self, bit, val): + self.i2c.writeto(TM1650_DSP + bit % 4, val.to_bytes(1, 'little')) + + def clear(self): + self.dat(0, 0) + self.dat(1, 0) + self.dat(2, 0) + self.dat(3, 0) + self.dbuf = [0, 0, 0, 0] + + def showbit(self, num, bit=0): + self.dbuf[bit % 4] = _SEGMENTS[num % 16] + self.dat(bit, _SEGMENTS[num % 16]) + + def shownum(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num // 1000) % 10) + self.showbit(num % 10, 3) + self.showbit((num // 10) % 10, 2) + self.showbit((num // 100) % 10, 1) + + def showhex(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num >> 12) % 16) + self.showbit(num % 16, 3) + self.showbit((num >> 4) % 16, 2) + self.showbit((num >> 8) % 16, 1) + + def showDP(self, bit=1, show=True): + if show: + self.dat(bit, self.dbuf[bit] | 0x80) + else: + self.dat(bit, self.dbuf[bit] & 0x7F) diff --git a/mixly/boards/default/micropython/build/lib/tm1652.py b/mixly/boards/default/micropython/build/lib/tm1652.py new file mode 100644 index 00000000..c9b96685 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/tm1652.py @@ -0,0 +1,78 @@ +""" +TM1652-framebuf + +Micropython library for the TM1652 Matrix8x5 +======================================================= + +#Preliminary composition 20230126 + +@dahanzimin From the Mixly Team +""" +import time +import uframebuf +from machine import Pin +from micropython import const + +_TM1652_REG_ADD = const(0x08) #Display address command +_TM1652_REG_CMD = const(0x18) #Display control command +_TM1652_SET_CUR = const(0x04) #LED current setting 3/8 + +class TM1652(uframebuf.FrameBuffer_Ascall): + def __init__(self, pin, brightness=0.3, width=8, height=5): + self.pin=Pin(pin,Pin.OUT) + self.pin.value(1) + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_HMSB) + self.brightness = brightness + self._brightness = None + self.set_brightness(brightness) + time.sleep_ms(5) + self.fill(0) + self.show() + + def _write_cmd(self, val): + '''Serial write command''' + falg=0 + #Start bit + self.pin.value(1) + time.sleep_us(15) + self.pin.value(0) + time.sleep_us(30) + #Data bits + for i in range(8): + if (val >> i) & 0x01: + self.pin.value(1) + falg+=1 + else: + self.pin.value(0) + falg+=0 + time.sleep_us(44) + #Check bit + self.pin.value(1) if falg%2 == 0 else self.pin.value(0) + time.sleep_us(50) + #Stop bit + self.pin.value(1) + time.sleep_us(15) + + def get_brightness(self): + return round(self.brightness,2) + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0~1.0") + self.brightness = brightness + xbright = round(15 * brightness) + xbright = ((xbright & 0xA) >>1) | ((xbright & 0x5) <<1) + xbright = ((xbright & 0xC) >>2) | ((xbright & 0x3) <<2) + self._brightness = (xbright << 4) | _TM1652_SET_CUR #高四位倒序|驱动电流 + + def show(self): + """Refresh the display and show the changes.""" + for _ in range(2): + self._write_cmd(_TM1652_REG_ADD) + for i in range(5): + self._write_cmd(self._buffer[i]) + time.sleep_ms(3) + self._write_cmd(_TM1652_REG_CMD) + self._write_cmd(self._brightness) + time.sleep_ms(3) diff --git a/mixly/boards/default/micropython/build/lib/tm1680.py b/mixly/boards/default/micropython/build/lib/tm1680.py new file mode 100644 index 00000000..ea078aad --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/tm1680.py @@ -0,0 +1,68 @@ +""" +TM1680 + +library for the TM1680 Matrix32x12 +======================================================= + +#Preliminary composition 20230412 + +@dahanzimin From the Mixly Team +""" +import uframebuf +from micropython import const + +TM1680_SYS_EN = const(0x81) +TM1680_LED_ON = const(0x83) +TM1680_COM_16N = const(0xA4) + +class TM1680(uframebuf.FrameBuffer_Uincode): + def __init__(self, i2c, address=0x72, brightness=0.3, width=32, height=12): + self._device= i2c + self._address = address + self._blink_rate=0 + self._brightness=brightness + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_HMSB) + self._write_cmd(TM1680_SYS_EN) #打开系统振荡器 + self._write_cmd(TM1680_LED_ON) #开启 LED 循环 + self._write_cmd(TM1680_COM_16N) #16COM Nmos + self.blink_rate(0) + self.set_brightness(brightness) + self.fill(0) + self.show() + + def _write_cmd(self, val): + '''I2C write command''' + self._device.writeto(self._address,val.to_bytes(1, 'little')) + + def blink_rate(self, rate=None): + if rate is None: + return self._blink_rate + if not 0 <= rate <= 3: + raise ValueError("Blink rate must be an integer in the range: 0-3") + rate = rate & 0x03 + self._blink_rate = rate + self._write_cmd(0x88 | rate) + + def get_brightness(self): + return self._brightness + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0-1.0") + self._brightness = brightness + xbright = round(15 * brightness) + xbright = xbright & 0x0F + self._write_cmd(0xB0 | xbright) + + def show(self): + """Refresh the display and show the changes.""" + tm_buffer = bytearray(48) + for i in range(len(self._buffer)): + if i<24: #Convert the buffer content according to the address of tm1680 + tm_buffer[i]=self._buffer[i*2-1] if i%2 else self._buffer[i*2] + else: + tm_buffer[i]=self._buffer[(i-23)*2-1] if i%2 else self._buffer[(i-23)*2] + #Convert the high and low 4 bits of the address content + tm_buffer[i]= (tm_buffer[i]>>4) | (tm_buffer[i] <<4) + self._device.writeto_mem(self._address,0x00,tm_buffer) diff --git a/mixly/boards/default/micropython/build/lib/tm1931.py b/mixly/boards/default/micropython/build/lib/tm1931.py new file mode 100644 index 00000000..e97b9704 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/tm1931.py @@ -0,0 +1,67 @@ +""" +TM1931- + +Micropython library for the TM1931 (18 channel IO port extension) +======================================================= + +#Preliminary composition 20220614 + +dahanzimin From the Mixly Team +""" + +import time +import framebuf +from machine import UART +from micropython import const + +_TM1931_ADDRESS = const(0x54) +_TM1931_REG_SSD = const(0x00) +_TM1931_REG_UPD = const(0x16) +_TM1931_REG_RST = const(0x17) + +class TM1931: + def __init__(self, i2c_bus, addr=_TM1931_ADDRESS): + self._i2c=i2c_bus + self._addr = addr + self._duty = bytearray(18) + self.reset() + + def _wreg(self, reg, val): + '''Write memory address''' + self._i2c.writeto_mem(self._addr,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._i2c.readfrom_mem(self._addr, reg, nbytes)[0] if nbytes<=1 else self._i2c.readfrom_mem(self._addr, reg, nbytes)[0:nbytes] + + def work(self,start=True): + """Start and open all output channels""" + self._wreg(_TM1931_REG_SSD,0x01& start) + start=0xff if start else 0 + for i in range(0x13,0x16,1): + self._wreg(i,start) + + def update(self): + """Load PWM register and LED control register data""" + self._wreg(_TM1931_REG_UPD,0xff) + + def reset(self): + """Reset all registers to default state""" + self._wreg(_TM1931_REG_RST,0x00) + self.work(True) + + def duty(self,index): + """Obtain PWM duty cycle""" + if not 1 <= index <= 18: + raise ValueError("Port must be a number in the range: 1-18") + return self._duty[index-1] + + def pwm(self,index,duty): + """18 channel PWM duty cycle data register""" + if not 0 <= duty <= 255: + raise ValueError("Duty must be a number in the range: 0-255") + if not 1 <= index <= 18: + raise ValueError("Port must be a number in the range: 1-18") + self._duty[index-1] = duty + self._wreg(index,duty) + self.update() diff --git a/mixly/boards/default/micropython/build/lib/tvoc07s.py b/mixly/boards/default/micropython/build/lib/tvoc07s.py new file mode 100644 index 00000000..dd509b8b --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/tvoc07s.py @@ -0,0 +1,39 @@ +""" +TVOC + +Micropython library for the TVOC(UART) +======================================================= +@dahanzimin From the Mixly Team +""" +import time + +class TVOC: + def __init__(self, uart): + self._uart = uart + self._uart.init(baudrate=9600) + self._tvoc = (0, 0 ,0) #TVOC mg/m3, CH2O mg/m3, C02 ppm + self._flag = False + if not self._chip_id(): + raise AttributeError("Cannot find a TOVC") + + def _rreg(self): + '''Read data''' + if self._uart.any(): + eec = 0 + buf = self._uart.read(9) + for i in buf[:8]: + eec += i + if (eec & 0xFF) == buf[8] and buf[0] == 0x2C: + self._tvoc=((buf[2] << 8 | buf[3]) * 0.001, (buf[4] << 8 | buf[5]) * 0.001, buf[6] << 8 | buf[7] ) + return True + + def _chip_id(self): + for _ in range(5): + if self._rreg(): + return True + time.sleep(1) + return False + + def read(self): + self._rreg() + return self._tvoc diff --git a/mixly/boards/default/micropython/build/lib/uart_com.py b/mixly/boards/default/micropython/build/lib/uart_com.py new file mode 100644 index 00000000..aee88755 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/uart_com.py @@ -0,0 +1,27 @@ +""" +UART Communication + +MicroPython library for the UART_COM(Board to board communication) +======================================================= +#Preliminary composition 20220903 + +dahanzimin From the Mixly Team +""" +_sdata=None + +def send(uart,data,repeat=True): + global _sdata + if data != _sdata: + uart.write((str(data)+'\n')) + if not repeat: + _sdata=data + +def recv(uart): + data = uart.readline() + if data: + data_str = data.strip() + try: + data_str=data_str.decode() + return eval(data_str) + except: + return data_str diff --git a/mixly/boards/default/micropython/build/lib/ucs12071.py b/mixly/boards/default/micropython/build/lib/ucs12071.py new file mode 100644 index 00000000..303b94ef --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ucs12071.py @@ -0,0 +1,78 @@ +""" +UCS12071 + +MicroPython library for the UCS12071 (Color sensor) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +UCS_SYSM_CTRL = const(0x00) +UCS_INT_FLAG = const(0x02) +UCS_WAIT_TIME = const(0x03) +UCS_CLS_GAIN = const(0x04) +UCS_CLS_TIME = const(0x05) +UCS_CLS_DATA = const(0x1C) + +_GAINS_X = (1, 4, 8, 32, 96, 192) + +class UCS12071: + def __init__(self, i2c_bus, addr=0x38, gain=2): + self._device = i2c_bus + self._address = addr + self._gain = gain + self._color = [0, 0, 0] + self._ir = 0 + self._als = 0 + self._configure() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _configure(self): + '''Configuration Register''' + #self._wreg(UCS_SYSM_CTRL, 0x80) #Software reset + self._wreg(UCS_SYSM_CTRL, 0x03) #CLS & IR Enable + self._wreg(UCS_CLS_GAIN, 1 << self._gain | 0x80) #CLS sensing gain + self._wreg(UCS_CLS_TIME, 0x03) #CLSCONV INT_TIME + self._wreg(UCS_WAIT_TIME, 0x00) #10ms per time unit + + def status(self): + '''Data conversion status''' + return self._rreg(UCS_INT_FLAG) & 0x40 + + def getdata(self): + '''Processing data acquisition''' + if not self.status(): + _buf = self._rreg(UCS_CLS_DATA, 10) + self._color[0] = _buf[0] | _buf[1] << 8 + self._color[1] = _buf[2] | _buf[3] << 8 + self._color[2] = _buf[4] | _buf[5] << 8 + self._als = _buf[6] | _buf[7] << 8 + self._ir = _buf[8] | _buf[9] << 8 + return self._als, self._ir, self._color + + def color(self): + w, _, (r, g, b) = self.getdata() + if w == 0: + return (0, 0, 0) + else: + red = int(pow((int((r / w) * 256) / 255), 2.5) * 255) + green = int(pow((int((g / w) * 256) / 255), 2.5) * 255) + blue = int(pow((int((b / w) * 256) / 255), 2.5) * 255) + return (min(red, 255), min(green, 255), min(blue, 255)) + + def color_raw(self): + return self.getdata()[2] + + def ir(self): + return round(self.getdata()[1] / _GAINS_X[self._gain]) + + def als(self): + return round(self.getdata()[0] / _GAINS_X[self._gain]) diff --git a/mixly/boards/default/micropython/build/lib/uframebuf.py b/mixly/boards/default/micropython/build/lib/uframebuf.py new file mode 100644 index 00000000..2dfa073e --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/uframebuf.py @@ -0,0 +1,573 @@ +""" +framebuf-extend + +Micropython library for the framebuf-extend +======================================================= +@dahanzimin From the Mixly Team +""" + +import esp, time, gc, math +from framebuf import * + +class Font_Ascall: + '''Ascall code font reading data''' + #字库格式:2字节字宽和高,后逐列式,按满字节低位在前 + font4x5_code=b'\x04\x05\x00\x00\x00\x00\x00\x17\x00\x00\x03\x00\x03\x00\x1f\n\x1f\x00\x16\x1f\x1a\x00\x19\x04\x13\x00\n\x15\x1a\x00\x00\x01\x03\x00\x00\x0e\x11\x00\x11\x0e\x00\x00\x15\x0e\x15\x00\x04\x0e\x04\x00\x00\x08\x18\x00\x04\x04\x04\x00\x18\x18\x00\x00\x18\x04\x03\x00\x1f\x11\x1f\x00\x12\x1f\x10\x00\x1d\x15\x17\x00\x15\x15\x1f\x00\x07\x04\x1f\x00\x17\x15\x1d\x00\x1f\x15\x1d\x00\x01\x01\x1f\x00\x1f\x15\x1f\x00\x17\x15\x1f\x00\x1b\x1b\x00\x00\x00\x0b\x1b\x00\x04\n\x11\x00\n\n\n\x00\x11\n\x04\x00\x01\x15\x07\x00\x0e\x15\x16\x00\x1e\x05\x1e\x00\x1f\x15\n\x00\x0e\x11\x11\x00\x1f\x11\x0e\x00\x1f\x15\x15\x00\x1f\x05\x05\x00\x0e\x15\x1d\x00\x1f\x04\x1f\x00\x11\x1f\x11\x00\x08\x11\x0f\x00\x1f\x0c\x12\x00\x1f\x10\x10\x00\x1f\x02\x1f\x00\x1e\x04\x0f\x00\x0e\x11\x0e\x00\x1f\x05\x02\x00\x0e\x19\x1e\x00\x1f\t\x16\x00\x12\x15\t\x00\x01\x1f\x01\x00\x1f\x10\x1f\x00\x0f\x10\x0f\x00\x1f\x08\x1f\x00\x1b\x04\x1b\x00\x07\x1c\x07\x00\x19\x15\x13\x00\x00\x1f\x11\x00\x03\x0c\x10\x00\x11\x1f\x00\x00\x02\x01\x02\x00\x10\x10\x10\x00\x00\x03\x02\x00\n\x16\x1e\x00\x1f\x14\x08\x00\x0c\x12\x12\x00\x08\x14\x1f\x00\x0c\x1a\x14\x00\x04\x1e\x05\x00\x14\x1a\x1e\x00\x1f\x04\x18\x00\x00\x1d\x00\x00\x10\x1d\x00\x00\x1e\x08\x14\x00\x00\x1e\x00\x00\x1e\x04\x1e\x00\x1e\x02\x1e\x00\x0c\x12\x0c\x00\x1e\n\x04\x00\x04\n\x1e\x00\x1e\x04\x02\x00\x12\x15\t\x00\x04\x1e\x14\x00\x1e\x10\x1e\x00\x0e\x10\x0e\x00\x1e\x08\x1e\x00\x12\x0c\x12\x00\x16\x18\x0e\x00\x19\x15\x13\x00\x04\x1f\x11\x00\x00\x1f\x00\x00\x11\x1f\x04\x00\x02\x06\x04\x00\x15\n\x15\x00' + font5x5_code=b'\x05\x05\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x03\x00\x03\x00\n\x1f\n\x1f\n\n\x17\x15\x1d\n\x13\t\x04\x12\x19\n\x15\x15\n\x10\x00\x03\x00\x00\x00\x00\x0e\x11\x00\x00\x00\x11\x0e\x00\x00\x00\n\x04\n\x00\x00\x04\x0e\x04\x00\x00\x10\x08\x00\x00\x00\x04\x04\x04\x00\x00\x08\x00\x00\x00\x10\x08\x04\x02\x01\x0e\x11\x11\x0e\x00\x00\x12\x1f\x10\x00\x19\x15\x15\x12\x00\t\x11\x15\x0b\x00\x0c\n\t\x1f\x08\x17\x15\x15\x15\t\x08\x14\x16\x15\x08\x11\t\x05\x03\x01\n\x15\x15\x15\n\x02\x15\r\x05\x02\x00\n\x00\x00\x00\x00\x10\n\x00\x00\x00\x04\n\x11\x00\x00\n\n\n\x00\x00\x11\n\x04\x00\x02\x01\x15\x05\x02\x0e\x11\x15\t\x0e\x1e\x05\x05\x1e\x00\x1f\x15\x15\n\x00\x0e\x11\x11\x11\x00\x1f\x11\x11\x0e\x00\x1f\x15\x15\x11\x00\x1f\x05\x05\x01\x00\x0e\x11\x11\x15\x0c\x1f\x04\x04\x1f\x00\x11\x1f\x11\x00\x00\t\x11\x11\x0f\x01\x1f\x04\n\x11\x00\x1f\x10\x10\x10\x00\x1f\x02\x04\x02\x1f\x1f\x02\x04\x08\x1f\x0e\x11\x11\x0e\x00\x1f\x05\x05\x02\x00\x06\t\x19\x16\x00\x1f\x05\x05\n\x10\x12\x15\x15\x08\x00\x01\x01\x1f\x01\x01\x0f\x10\x10\x0f\x00\x07\x08\x10\x08\x07\x07\x08\x10\x08\x07\x1b\x04\x04\x1b\x00\x01\x02\x1c\x02\x01\x19\x15\x13\x11\x00\x00\x1f\x11\x11\x00\x01\x02\x04\x08\x10\x00\x11\x11\x1f\x00\x00\x02\x01\x02\x00\x10\x10\x10\x10\x10\x00\x01\x02\x00\x00\x0c\x12\x12\x1e\x10\x1f\x14\x14\x08\x00\x0c\x12\x12\x12\x00\x08\x14\x14\x1f\x00\x0e\x15\x15\x12\x00\x04\x1e\x05\x01\x00\x02\x15\x15\x0f\x00\x1f\x04\x04\x18\x00\x00\x1d\x00\x00\x00\x00 \x1d\x00\x1f\x04\n\x10\x00\x00\x0f\x10\x10\x00\x1e\x02\x04\x02\x1e\x1e\x02\x02\x1c\x00\x0c\x12\x12\x0c\x00\x1e\n\n\x04\x00\x04\n\n\x1e\x00\x1c\x02\x02\x02\x00\x10\x14\n\x02\x00\x00\x0f\x14\x14\x10\x0e\x10\x10\x1e\x10\x06\x08\x10\x08\x06\x1e\x10\x08\x10\x1e\x12\x0c\x0c\x12\x00\x12\x14\x08\x04\x02\x12\x1a\x16\x12\x00\x00\x04\x1f\x11\x00\x00\x1f\x00\x00\x00\x11\x1f\x04\x00\x00\x00\x04\x04\x08\x08\x02\x06\x06\x06\x06' + font5x8_code=b'\x05\x08\x00\x00\x00\x00\x00\x00\x00_\x00\x00\x00\x07\x00\x07\x00\x14\x7f\x14\x7f\x14$*\x7f*\x12#\x13\x08db6IV P\x00\x08\x07\x03\x00\x00\x1c"A\x00\x00A"\x1c\x00*\x1c\x7f\x1c*\x08\x08>\x08\x08\x00\x80p0\x00\x08\x08\x08\x08\x08\x00\x00``\x00 \x10\x08\x04\x02>QIE>\x00B\x7f@\x00rIIIF!AIM3\x18\x14\x12\x7f\x10\'EEE9A]YN|\x12\x11\x12|\x7fIII6>AAA"\x7fAAA>\x7fIIIA\x7f\t\t\t\x01>AAQs\x7f\x08\x08\x08\x7f\x00A\x7fA\x00 @A?\x01\x7f\x08\x14"A\x7f@@@@\x7f\x02\x1c\x02\x7f\x7f\x04\x08\x10\x7f>AAA>\x7f\t\t\t\x06>AQ!^\x7f\t\x19)F&III2\x03\x01\x7f\x01\x03?@@@?\x1f @ \x1f?@8@?c\x14\x08\x14c\x03\x04x\x04\x03aYIMC\x00\x7fAAA\x02\x04\x08\x10 \x00AAA\x7f\x04\x02\x01\x02\x04@@@@@\x00\x03\x07\x08\x00 TTx@\x7f(DD88DDD(8DD(\x7f8TTT\x18\x00\x08~\t\x02\x18\xa4\xa4\x9cx\x7f\x08\x04\x04x\x00D}@\x00 @@=\x00\x7f\x10(D\x00\x00A\x7f@\x00|\x04x\x04x|\x08\x04\x04x8DDD8\xfc\x18$$\x18\x18$$\x18\xfc|\x08\x04\x04\x08HTTT$\x04\x04?D$<@@ |\x1c @ \x1c<@0@> 26 + buffer = bytearray(self.height*(font_width // 8 + 1)) + esp.flash_read(self.start_address + font_address, buffer) + return buffer, (font_width, self.height) + +class Image: + def load(self, path, invert=0): + self.invert = invert + with open(path, 'rb') as file: + image_type = file.read(2).decode() + file.seek(0) + img_arrays = bytearray(file.read()) + if image_type == 'P4': + buffer = self._pbm_decode(img_arrays) + elif image_type == 'BM': + buffer = self._bmp_decode(img_arrays) + else: + raise TypeError("Unsupported image format {}".format(image_type)) + gc.collect() + return buffer + + def load_py(self, name, invert=0): + self.invert = invert + image_type = name[0:2] + if image_type == b'P4': + buffer = self._pbm_decode(bytearray(name)) + elif image_type == b'BM': + buffer = self._bmp_decode(bytearray(name)) + else: + raise TypeError("Unsupported image format {}".format(image_type)) + gc.collect() + return buffer + + def _pbm_decode(self, img_arrays): + next_value = bytearray() + pnm_header = [] + stat = True + index = 3 + while stat: + next_byte = bytes([img_arrays[index]]) + if next_byte == b"#": + while bytes([img_arrays[index]]) not in [b"", b"\n"]: + index += 1 + if not next_byte.isdigit(): + if next_value: + pnm_header.append(int("".join(["%c" % char for char in next_value]))) + next_value = bytearray() + else: + next_value += next_byte + if len(pnm_header) == 2: + stat = False + index += 1 + pixel_arrays = img_arrays[index:] + if self.invert == 1: + for i in range(len(pixel_arrays)): + pixel_arrays[i] = (~pixel_arrays[i]) & 0xff + return pixel_arrays,(pnm_header[0], pnm_header[1]) + + def _bmp_decode(self, img_arrays): + file_size = int.from_bytes(img_arrays[2:6], 'little') + offset = int.from_bytes(img_arrays[10:14], 'little') + width = int.from_bytes(img_arrays[18:22], 'little') + height = int.from_bytes(img_arrays[22:26], 'little') + bpp = int.from_bytes(img_arrays[28:30], 'little') + if bpp != 1: + raise TypeError("Only support 1 bit color bmp") + line_bytes_size = (bpp * width + 31) // 32 * 4 + array_size = width * abs(height) // 8 + pixel_arrays = bytearray(array_size) + array_row = width // 8 + 1 if width % 8 else width // 8 + array_col = height + for i in range(array_col): + for j in range(array_row): + index = -(array_row * (i + 1) - j) + _offset = offset + i * line_bytes_size + j + if self.invert == 0: + pixel_byte = (~img_arrays[_offset]) & 0xff + else: + pixel_byte = img_arrays[_offset] + pixel_arrays[index] = pixel_byte + return pixel_arrays,(width, height) + +class FrameBuffer_Base(FrameBuffer): + """Inheritance and Extension""" + def __init__(self, buf, width, height, *args, **kw): + super().__init__(buf, width, height, *args, **kw) + self.width = width + self.height = height + self._buffer = buf + self._way = 1 + self._speed = 100 + self._miniqr = None + + def show(self): + print("External inheritance is required to override this method") + + def write(self): + self.show() + + def shift(self, x, y, rotate=False, sync=True): + """Shift pixels by x and y""" + if x > 0: # Shift Right + for _ in range(x): + for row in range(0, self.height): + last_pixel = super().pixel(self.width - 1, row) if rotate else 0 + for col in range(self.width - 1, 0, -1): + super().pixel(col, row, super().pixel(col - 1, row)) + super().pixel(0, row, last_pixel) + elif x < 0: # Shift Left + for _ in range(-x): + for row in range(0, self.height): + last_pixel = super().pixel(0, row) if rotate else 0 + for col in range(0, self.width - 1): + super().pixel(col, row, super().pixel(col + 1, row)) + super().pixel(self.width - 1, row, last_pixel) + if y > 0: # Shift Up + for _ in range(y): + for col in range(0, self.width): + last_pixel = super().pixel(col, self.height - 1) if rotate else 0 + for row in range(self.height - 1, 0, -1): + super().pixel(col, row, super().pixel(col, row - 1)) + super().pixel(col, 0, last_pixel) + elif y < 0: # Shift Down + for _ in range(-y): + for col in range(0, self.width): + last_pixel = super().pixel(col, 0) if rotate else 0 + for row in range(0, self.height - 1): + super().pixel(col, row, super().pixel(col, row + 1)) + super().pixel(col, self.height - 1, last_pixel) + if sync: self.show() + + def shift_right(self, num, rotate=False, sync=True): + """Shift all pixels right""" + self.shift(num, 0, rotate, sync) + + def shift_left(self, num, rotate=False, sync=True): + """Shift all pixels left""" + self.shift(-num, 0, rotate, sync) + + def shift_up(self, num, rotate=False, sync=True): + """Shift all pixels up""" + self.shift(0, -num, rotate, sync) + + def shift_down(self, num, rotate=False, sync=True): + """Shift all pixels down""" + self.shift(0, num, rotate, sync) + + def map_invert(self, own): + """Graph invert operation""" + if type(own) in [list, bytes, tuple, bytearray]: + result=bytearray() + for i in range(len(own)): + result.append(~ own[i]) + return result + else: + raise ValueError("This graphic operation is not supported") + + def map_add(self, own, other): + """Graph union operation""" + if type(own) in [list, bytes, tuple, bytearray] and type(other) in [list, bytes, tuple, bytearray]: + result=bytearray() + for i in range(min(len(own), len(other))): + result.append(own[i] | other[i]) + return result + else: + raise ValueError("This graphic operation is not supported") + + def map_sub(self, own, other): + """Graphic subtraction operation""" + if type(own) in [list, bytes, tuple, bytearray] and type(other) in [list, bytes, tuple, bytearray]: + result=bytearray() + for i in range(min(len(own), len(other))): + result.append((own[i] ^ other[i]) & own[i]) + return result + else: + raise ValueError("This graphic operation is not supported") + + def set_buffer(self, buffer, sync=True): + for i in range(min(len(buffer),len(self._buffer))): + self._buffer[i] = self._buffer[i] | buffer[i] + if sync: self.show() + + def get_buffer(self): + return self._buffer + + def pointern(self, x=None, y=None, l=None, angle=0, color=0xffff, bg_color=0x0, sync=True): + x = self.width // 2 if x is None else x + y = self.height // 2 if y is None else y + l = min(self.height // 2 , self.width // 2) if l is None else l + radian = math.radians(angle) + if sync: super().fill(bg_color) + super().line(x, y, round(x + l * math.sin(radian)), round(y - l * math.cos(radian)), color) + if sync: self.show() + + def pixel(self, x, y, color=None, sync=True): + if color is None: + return super().pixel(x, y) + else: + super().pixel(x, y, color) + if sync: self.show() + + def vline(self, x, y, h, c, sync=True): + super().vline(x, y, h, c) + if sync: self.show() + + def hline(self, x, y, w, c, sync=True): + super().hline(x, y, w, c) + if sync: self.show() + + def line(self, x1, y1, x2, y2, c, sync=True): + super().line(x1, y1, x2, y2, c) + if sync: self.show() + + def rect(self, x, y, w, h, c, sync=True): + super().rect(x, y, w, h, c) + if sync: self.show() + + def fill_rect(self, x, y, w, h, c, sync=True): + super().fill_rect(x, y, w, h, c) + if sync: self.show() + + def ellipse(self, x, y, xr, yr, c, f=False, sync=True): + super().ellipse(x, y, xr, yr, c, f) + if sync: self.show() + + def fill(self, c, sync=True): + super().fill(c) + if sync: self.show() + +class FrameBuffer_Ascall(FrameBuffer_Base): + '''FrameBuffer for Ascall''' + def font(self, font): + """Font selection or externally defined font code""" + self._font = Font_Ascall(font) + + def uin_font(self, font_address=0x3A0000): + """Uincode encoding font code""" + self._ufont = Font_Uincode(font_address) + + def scroll_way(self, way=1, speed=None): + """0,1竖,2,3横""" + self._way = way % 4 + if speed is not None: + self._speed = speed + + def bitmap(self, buffer, x=0, y=0): + """Graphic model display(buffer,(width,height))""" + buffer_info, (width, height) = buffer + if x < -width or x >= self.width or y < -height or y >= self.height: + return #Limit reasonable display area + for char_x in range(width): + for char_y in range(height): + if (buffer_info[char_x] >> char_y) & 0x1: + self.pixel(x + char_x, y + char_y, 1, sync=False) if height <= self.height else self.pixel(y + char_y, self.height - (x + char_x), 1, sync=False) + + def _uincode_scroll(self, buffer, space): + """Scroll to display uincode encoded characters""" + _len = 0 + for buf in buffer: + _len = _len + space + (buf[1][1] if self._way <= 1 else buf[1][0]) + for i in range(_len - space + (self.width if self._way <= 1 else self.height)): + _step = (self.width - 1 if self._way <= 1 else self.height) - i + self.fill(0, sync=False) + for buf in buffer: + _buf, (width, height) = buf + _xx = (self.width - width) // 2 + _yy = (self.width - height) // 2 + if -width < _step < self.width or -height < _step < self.height : + for _y in range(height): + for _x in range(width): + if _buf[_y * ((width + 7) // 8) + _x // 8] & (0x80 >> (_x & 7)): + if self._way == 0: + self.pixel(self.width - (_x + _xx) - 2, self.height - (_step + _y), 1, sync=False) + elif self._way == 1: + self.pixel(_xx + _x + 1, _step + _y, 1, sync=False) + elif self._way == 2: + self.pixel(_y +_yy, self.height - (_step + _x), 1, sync=False) + elif self._way == 3: + self.pixel(self.width - (_y +_yy) - 1, (_step + _x), 1, sync=False) + _step = _step + space + (height if self._way <= 1 else width) + self.show() + time.sleep_ms(self._speed) + + def _gb2312_scroll(self, data, space): + """Determine if the uincode is encoded""" + for char in data: + if ord(char) >= 0xFF: + font_buffer = [] + for c in data: + _buffer = self._ufont.chardata(c) + font_buffer.append(_buffer) + self._uincode_scroll(font_buffer, space) + return True + + def shows(self, data, space=0, center=True, sync=True): + """Display character""" + if data is not None: + self.fill(0, sync=False) + if type(data) in [list, bytes, tuple, bytearray]: + self.set_buffer(data, sync) + else: + data=str(data) + if not self._gb2312_scroll(data, space): + x = (self.width - len(data) * (self._font.font_width + space) + space) // 2 if center else 0 + for char in data: + self.bitmap(self._font.chardata(char), x) + x = self._font.font_width + x + space + if sync: self.show() + + def frame(self, data, delay=500): + """Display one frame per character""" + if data is not None: + if type(data) in [list,tuple]: + for dat in data: + if type(dat) in [list,bytes,tuple,bytearray]: + self.fill(0, sync=False) + self.set_buffer(data, True) + time.sleep_ms(delay) + else: + data=str(data) + for char in data: + self.fill(0, sync=False) + if ord(char) >= 0xFF: + _way = self._way + self._way = 1 + self._uincode_scroll([self._ufont.chardata(char)], 0) + self._way = _way + else: + self.bitmap(self._font.chardata(char), (self.width - self._font.font_width) // 2 ) + self.show() + time.sleep_ms(delay) + + def scroll(self, data, space=0, speed=None): + """Scrolling characters""" + if speed is not None: + self._speed = speed + if data is not None: + data = str(data) + if not self._gb2312_scroll(data, space): + str_len = len(data) * (self._font.font_width + space) - space + for i in range(str_len + self.width + 1): + x = -i + self.width + self.fill(0, sync=False) + for char in data: + self.bitmap(self._font.chardata(char),x) + x = self._font.font_width + x + space + self.show() + time.sleep_ms(self._speed) + +class FrameBuffer_Uincode(FrameBuffer_Base): + '''FrameBuffer for Uincode''' + def font(self, font_address=0x700000): + """Font selection or externally defined font code""" + self._font = Font_Uincode(font_address) + + def shift(self, x, y, rotate=False, sync=True): + '''Reshaping Inheritance Methods''' + super().scroll(x, y) + if sync: self.show() + + def image(self, path, x=None, y=None, size=None, invert=0, color=0xffff, bold=0, sync=True): + """Set buffer to value of Python Imaging Library image""" + if type(path) is str : + buffer_info, (width, height) = Image().load(path, invert) + elif type(path) in [bytes, bytearray]: + buffer_info, (width, height) = Image().load_py(path, invert) + else: + raise ValueError("invalid input") + if width > self.width or height > self.height: + raise ValueError("Image must be less than display ({0}x{1}).".format(self.width, self.height)) + size = min(self.height // height, self.width // width) if size is None else size + size = max(round(size), 1) + x =(self.width - width * size) // 2 if x is None else x + y =(self.height - height * size) // 2 if y is None else y + if sync: self.fill_rect(x, y, width * size, height * size, 0, sync=False) + self.bitmap((buffer_info,(width, height)), x, y, size, bold, color) + if sync: self.show() + + def bitmap(self, buffer, x=0, y=0, size=1, bold=0, color=0xffff): + """Graphic model display(buffer,(width,height))""" + buffer_info,(width,height)=buffer + if x < -width*size or x >= self.width or y < -height*size or y >= self.height: + return #Limit reasonable display area + bytewidth = (width + 7) // 8 + for j in range(height): + for i in range(width): + if buffer_info[j * bytewidth + i // 8] & (0x80 >> (i & 7)): + self.fill_rect(x + i * size, y + j * size, int(size + bold), int(size + bold), color, sync=False) + + def _take_buffer(self, strs, space, size=1): + '''Get character lattice information first''' + font_buffer = [] + font_len = 0 + for c in strs: + buffer = self._font.chardata(c) + font_buffer.append(buffer) + font_len = font_len + buffer[1][0] * size + space + return font_len, font_buffer + + def shows(self, data, space=0, center=True, x=0, y=None, size=None, color=0xffff, bold=0, bg_color=0x0, sync=True): + """Display character""" + if data is not None: + if type(data) in [list, bytes, tuple, bytearray]: + if sync: self.fill(bg_color, sync=False) + self.set_buffer(data, sync) + else: + yy = y + if size is None: + font_len, font_buffer = self._take_buffer(str(data), space, 1) + size = min((self.width // font_len) if font_len > 0 else 1, self.height // self._font.height) + size = max(round(size), 1) + font_len, font_buffer = self._take_buffer(str(data), space, size) + x = (self.width - font_len + space) // 2 if center else x + y = (self.height - self._font.height * size) // 2 if y is None else y + if sync: + if yy is None: + self.fill(bg_color, sync=False) + else: + self.fill_rect(0, y - 1, self.width, self._font.height * size + 2, bg_color, sync=False) + for buffer in font_buffer: #Display character + self.bitmap(buffer, x, y, size, bold, color) + x = buffer[1][0] * size + x + space + if sync: self.show() + + def texts(self, data, space_x=0, space_y=1, x=0, y=0, size=1, color=0xffff, bold=0, bg_color=0x0, sync=True): + size = max(round(size), 1) + lines = data.split('\n') + if sync: self.fill(bg_color, sync=False) + for line in lines: + for char in line: + buffer = self._font.chardata(char) + if x > self.width - buffer[1][0] * size: + x = 0 + y = buffer[1][1] * size + y + space_y + if y > self.height: + if sync: self.show() + return None + self.bitmap(buffer, x, y, size, bold, color) + x = buffer[1][0] * size + x + space_x + x = 0 + y = self._font.height * size + y + space_y + if sync: self.show() + + def frame(self, data, delay=500, size=None, color=0xffff, bold=0, bg_color=0x0): + """Display one frame per character""" + if data is not None: + if type(data) in [list, tuple]: + for dat in data: + if type(dat) in [list, bytes, tuple, bytearray]: + self.fill(bg_color, sync=False) + self.set_buffer(data, True) + time.sleep_ms(delay) + else: + size = self.height // (self._font.height * 3) if size is None else size + size = max(round(size), 1) + _, font_buffer = self._take_buffer(str(data), 0) + for buffer in font_buffer: + x=(self.width - buffer[1][0] * size) // 2 + y=(self.height - buffer[1][1] * size) // 2 + self.fill(bg_color, sync=False) + self.bitmap(buffer, x, y, size, bold, color) + self.show() + time.sleep_ms(delay) + + def scroll(self, data, space=0, speed=20, y=None, size=None, step= None, color=0xffff, bold=0, bg_color=0x0): + """Scrolling characters""" + if data is not None: + size = self.height // (self._font.height * 3) if size is None else size + size = max(round(size), 1) + step = max(self.width // 30, 1)if step is None else step + font_len, font_buffer = self._take_buffer(str(data), space, size) + for i in range(0, font_len - space + self.width, step): + x = -i + self.width + y = (self.height - self._font.height * size) // 2 if y is None else y + self.fill_rect(x - 2 , y - 2 , self.width -x + 4, font_buffer[0][1][1] * size + 4, bg_color, sync=False) + for buffer in font_buffer: + self.bitmap(buffer, x, y, size, bold, color) + x = buffer[1][0] * size + x + space + self.show() + time.sleep_ms(speed) + + def qrcode(self, data, x=None, y=None, size=None, bold=0, type=None, correct=0, color=0xffff, bg_color=0x0, sync=True): + if self._miniqr is None: + from adafruit_miniqr import QRCode + self._miniqr = QRCode + _qr = self._miniqr(qr_type=type, error_correct=correct) + _qr.add_data(str(data)) + _qr.make() + if sync: self.fill(bg_color, sync=False) + size = min(self.height // _qr.matrix.height, self.width // _qr.matrix.width) if size is None else size + x = (self.width - _qr.matrix.width * size) // 2 if x is None else x + y = (self.height - _qr.matrix.height * size) // 2 if y is None else y + for j in range(_qr.matrix.height): + for i in range(_qr.matrix.width): + if _qr.matrix[i, j]: + self.fill_rect(x + i * size, y + j * size, int(size + bold), int(size + bold), color, sync=False) + del _qr + gc.collect() + if sync: self.show() diff --git a/mixly/boards/default/micropython/build/lib/umqtt.py b/mixly/boards/default/micropython/build/lib/umqtt.py new file mode 100644 index 00000000..21b781f6 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/umqtt.py @@ -0,0 +1,205 @@ +#Based on the traditional MQTT library +#@dahanzimin From the Mixly Team +import usocket as socket +import ustruct as struct + +# Add by Mixly Team +def str_len(object): + if isinstance(object, str): + return len(object.encode('utf-8')) + else: + return len(object) + +class MQTTException(Exception): + pass + +class MQTTClient: + def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,ssl=False, ssl_params={}): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = socket.socket() + self.addr = socket.getaddrinfo(server, port)[0][-1] + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self.cb = None + self.user = user + self.pswd = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + + def _send_str(self, s): + self.sock.write(struct.pack("!H", str_len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, f): + self.cb = f + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + self.sock.connect(self.addr) + print(self.addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) + msg_header=bytearray([0x10]) + msg = bytearray(b"\x04MQTT\x04\x02\0\0") + msg_length = 12 + str_len(self.client_id) + msg[6] = clean_session << 1 + if self.user is not None: + msg_length += 2 + str_len(self.user) + 2 + str_len(self.pswd) + msg[6] |= 0xC0 + if self.keepalive: + assert self.keepalive < 65536 + msg[7] |= self.keepalive >> 8 + msg[8] |= self.keepalive & 0x00FF + if self.lw_topic: + msg_length += 2 + str_len(self.lw_topic) + 2 + str_len(self.lw_msg) + msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 + msg[6] |= self.lw_retain << 5 + if msg_length > 0x7F: + while msg_length>0: + encoded_byte = msg_length % 0x80 + msg_length = msg_length // 0x80 + if msg_length > 0: + encoded_byte |= 0x80 + msg_header.append(encoded_byte) + msg_header.append(0x00) + else: + msg_header.append(msg_length) + msg_header.append(0x00) + self.sock.write(msg_header) + self.sock.write(msg) + + self._send_str(self.client_id) + if self.lw_topic: + self._send_str(self.lw_topic) + self._send_str(self.lw_msg) + if self.user is not None: + self._send_str(self.user) + self._send_str(self.pswd) + resp = self.sock.read(4) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + raise MQTTException(resp[3]) + return resp[2] & 1 + + def disconnect(self): + self.sock.write(b"\xe0\0") + self.sock.close() + + def ping(self): + self.sock.write(b"\xc0\0") + + def publish(self, topic, msg, retain=False, qos=0): + pkt = bytearray(b"\x30\0\0\0") + pkt[0] |= qos << 1 | retain + sz = 2 + str_len(topic) + str_len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.pid += 1 + pid = self.pid + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + if qos == 1: + while 1: + op = self.wait_msg() + if op == 0x40: + sz = self.sock.read(1) + assert sz == b"\x02" + rcv_pid = self.sock.read(2) + rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid == rcv_pid: + return + elif qos == 2: + assert 0 + + def subscribe(self, topic, qos=0): + pkt = bytearray(b"\x82\0\0\0") + self.pid += 1 + struct.pack_into("!BH", pkt, 1, 2 + 2 + str_len(topic) + 1, self.pid) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + while 1: + op = self.wait_msg() + if op == 0x90: + resp = self.sock.read(4) + assert resp[1] == pkt[2] and resp[2] == pkt[3] + if resp[3] == 0x80: + raise MQTTException(resp[3]) + return + + # Wait for a single incoming MQTT message and process it. + def wait_msg(self): + res = self.sock.read(1) + self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return None + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len).decode('utf-8') + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz).decode('utf-8') + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + if self.cb is None: + return {"msg":msg, "topic":topic} + else: + self.cb(topic, msg) + + # Checks whether a pending message from server is available. + def check_msg(self): + self.sock.setblocking(False) + return self.wait_msg() diff --git a/mixly/boards/default/micropython/build/lib/urequests.py b/mixly/boards/default/micropython/build/lib/urequests.py new file mode 100644 index 00000000..00c013f1 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/urequests.py @@ -0,0 +1,151 @@ +import usocket + +class Response: + + def __init__(self, f): + self.raw = f + self.encoding = "utf-8" + self._cached = None + + def close(self): + if self.raw: + self.raw.close() + self.raw = None + self._cached = None + + @property + def content(self): + if self._cached is None: + try: + self._cached = self.raw.read() + finally: + self.raw.close() + self.raw = None + return self._cached + + @property + def text(self): + return str(self.content, self.encoding) + + def json(self): + import ujson + return ujson.loads(self.content) + + +def request(method, url, data=None, json=None, headers={}, stream=None, parse_headers=True): + redir_cnt = 1 + while True: + try: + proto, dummy, host, path = url.split("/", 3) + except ValueError: + proto, dummy, host = url.split("/", 2) + path = "" + if proto == "http:": + port = 80 + elif proto == "https:": + import ssl + port = 443 + else: + raise ValueError("Unsupported protocol: " + proto) + + if ":" in host: + host, port = host.split(":", 1) + port = int(port) + + ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) + ai = ai[0] + + resp_d = None + if parse_headers is not False: + resp_d = {} + + s = usocket.socket(ai[0], ai[1], ai[2]) + try: + s.connect(ai[-1]) + if proto == "https:": + s = ssl.wrap_socket(s, server_hostname=host) + s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) + if not "Host" in headers: + s.write(b"Host: %s\r\n" % host) + # Iterate over keys to avoid tuple alloc + for k in headers: + s.write(k) + s.write(b": ") + s.write(headers[k]) + s.write(b"\r\n") + if json is not None: + assert data is None + import ujson + data = ujson.dumps(json) + s.write(b"Content-Type: application/json\r\n") + if data: + s.write(b"Content-Length: %d\r\n" % len(data)) + s.write(b"Connection: close\r\n\r\n") + if data: + s.write(data) + + l = s.readline() + #print(l) + l = l.split(None, 2) + status = int(l[1]) + reason = "" + if len(l) > 2: + reason = l[2].rstrip() + while True: + l = s.readline() + if not l or l == b"\r\n": + break + #print(l) + + if l.startswith(b"Transfer-Encoding:"): + if b"chunked" in l: + raise ValueError("Unsupported " + l) + elif l.startswith(b"Location:") and 300 <= status <= 399: + if not redir_cnt: + raise ValueError("Too many redirects") + redir_cnt -= 1 + url = l[9:].decode().strip() + #print("redir to:", url) + status = 300 + break + + if parse_headers is False: + pass + elif parse_headers is True: + l = l.decode() + k, v = l.split(":", 1) + resp_d[k] = v.strip() + else: + parse_headers(l, resp_d) + except OSError: + s.close() + raise + + if status != 300: + break + + resp = Response(s) + resp.status_code = status + resp.reason = reason + if resp_d is not None: + resp.headers = resp_d + return resp + + +def head(url, **kw): + return request("HEAD", url, **kw) + +def get(url, **kw): + return request("GET", url, **kw) + +def post(url, **kw): + return request("POST", url, **kw) + +def put(url, **kw): + return request("PUT", url, **kw) + +def patch(url, **kw): + return request("PATCH", url, **kw) + +def delete(url, **kw): + return request("DELETE", url, **kw) diff --git a/mixly/boards/default/micropython/build/lib/urllib.py b/mixly/boards/default/micropython/build/lib/urllib.py new file mode 100644 index 00000000..a02329fe --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/urllib.py @@ -0,0 +1,32 @@ +from ucollections import namedtuple + +URI = namedtuple('URI', ('cheme', 'netloc', 'path', 'params', 'query', 'fragment')) + +def quote(string, safe='_.-~+'): + """ A simple implementation of URL quoting""" + string = string.replace(' ', '+') + result = "" + for char in string: + if ('a' <= char <= 'z') or ('A' <= char <= 'Z') or ('0' <= char<= '9') or (char in safe): + result += char + else: + result += "%{:02X}".format(ord(char)) + return result + +def urlencode(query, safe='_.-~+'): + """A simple urlencode function""" + return '&'.join('{}={}'.format(quote(k, safe), quote(v, safe)) for k, v in query.items()) + +def urlparse(url): + """A simple urlparse (cheme, netloc, path, params, query, fragment)""" + parts = [''] * 6 + for i, sep in enumerate(['://', '#', '?', ';']): + if sep in url: + left, right = url.split(sep, 1) + parts[i], url = left, right + if '/' in url: + parts[1], parts[2] = url.split('/', 1) + parts[2] = '/' + parts[2] + else: + parts[1] = url + return URI(*parts) diff --git a/mixly/boards/default/micropython/build/lib/urllib_parse.py b/mixly/boards/default/micropython/build/lib/urllib_parse.py new file mode 100644 index 00000000..b3ffaf0d --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/urllib_parse.py @@ -0,0 +1,187 @@ +# Characters valid in scheme names +scheme_chars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "+-." + +# XXX: Consider replacing with functools.lru_cache +MAX_CACHE_SIZE = 20 + +_ALWAYS_SAFE = frozenset(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"abcdefghijklmnopqrstuvwxyz" b"0123456789" b"_.-") +_ALWAYS_SAFE_BYTES = bytes(_ALWAYS_SAFE) +_safe_quoters = {} + + +def clear_cache(): + """Clear the parse cache and the quoters cache.""" + _safe_quoters.clear() + + +_hexdig = "0123456789ABCDEFabcdef" +_hextobyte = {(a + b).encode(): bytes([int(a + b, 16)]) for a in _hexdig for b in _hexdig} + + +def unquote_to_bytes(string): + """unquote_to_bytes('abc%20def') -> b'abc def'.""" + # Note: strings are encoded as UTF-8. This is only an issue if it contains + # unescaped non-ASCII characters, which URIs should not. + if not string: + # Is it a string-like object? + string.split + return b"" + if isinstance(string, str): + string = string.encode("utf-8") + bits = string.split(b"%") + if len(bits) == 1: + return string + res = [bits[0]] + append = res.append + for item in bits[1:]: + try: + append(_hextobyte[item[:2]]) + append(item[2:]) + except KeyError: + append(b"%") + append(item) + return b"".join(res) + + +def split_on_non_ascii(s): + """ + Splits the input string wherever a character is not ASCII (ord(c) not in 0..127). + Returns a list of substrings and the non-ASCII characters as separate elements. + """ + result = [] + current = [] + for c in s: + if 0 <= ord(c) <= 127: + current.append(c) + else: + if current: + result.append("".join(current)) + current = [] + result.append(c) + if current: + result.append("".join(current)) + return result + + +def unquote(string, encoding="utf-8", errors="replace"): + """Replace %xx escapes by their single-character equivalent. The optional + encoding and errors parameters specify how to decode percent-encoded + sequences into Unicode characters, as accepted by the bytes.decode() + method. + By default, percent-encoded sequences are decoded with UTF-8, and invalid + sequences are replaced by a placeholder character. + + unquote('abc%20def') -> 'abc def'. + """ + if "%" not in string: + string.split + return string + if encoding is None: + encoding = "utf-8" + if errors is None: + errors = "replace" + bits = split_on_non_ascii(string) + res = [] + append = res.append + for i in range(0, len(bits), 2): + append(unquote_to_bytes(bits[i]).decode(encoding, errors)) + if i + 1 < len(bits): + # Append the non-ASCII part as is + append(bits[i + 1]) + return "".join(res) + + +class Quoter: + """A mapping from bytes (in range(0,256)) to strings. + + String values are percent-encoded byte values, unless the key < 128, and + in the "safe" set (either the specified safe set, or default set). + """ + + # Keeps a cache internally, using defaultdict, for efficiency (lookups + # of cached keys don't call Python code at all). + def __init__(self, safe): + """safe: bytes object.""" + self.safe = _ALWAYS_SAFE.union(safe) + self.cache = {} + + def get(self, b): + try: + return self.cache[b] + except KeyError: + # Handle a cache miss. Store quoted string in cache and return. + res = chr(b) if b in self.safe else "%{:02X}".format(b) + self.cache[b] = res + return res + + +def quote(string, safe="/", encoding=None, errors=None): + """quote('abc def') -> 'abc%20def' + + Each part of a URL, e.g. the path info, the query, etc., has a + different set of reserved characters that must be quoted. + + RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists + the following reserved characters. + + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + "$" | "," + + Each of these characters is reserved in some component of a URL, + but not necessarily in all of them. + + By default, the quote function is intended for quoting the path + section of a URL. Thus, it will not encode '/'. This character + is reserved, but in typical usage the quote function is being + called on a path where the existing slash characters are used as + reserved characters. + + string and safe may be either str or bytes objects. encoding must + not be specified if string is a str. + + The optional encoding and errors parameters specify how to deal with + non-ASCII characters, as accepted by the str.encode method. + By default, encoding='utf-8' (characters are encoded with UTF-8), and + errors='strict' (unsupported characters raise a UnicodeEncodeError). + """ + if isinstance(string, str): + if not string: + return string + if encoding is None: + encoding = "utf-8" + if errors is None: + errors = "strict" + string = string.encode(encoding, errors) + else: + if encoding is not None: + raise TypeError("quote() doesn't support 'encoding' for bytes") + if errors is not None: + raise TypeError("quote() doesn't support 'errors' for bytes") + return quote_from_bytes(string, safe) + + +def quote_from_bytes(bs, safe="/"): + """Like quote(), but accepts a bytes object rather than a str, and does + not perform string-to-bytes encoding. It always returns an ASCII string. + quote_from_bytes(b'abc def\x3f') -> 'abc%20def%3f' + """ + if not isinstance(bs, (bytes, bytearray)): + raise TypeError("quote_from_bytes() expected bytes") + if not bs: + return "" + if isinstance(safe, str): + # Normalize 'safe' by converting to bytes and removing non-ASCII chars + safe = safe.encode("ascii", "ignore") + else: + safe = bytes([c for c in safe if c < 128]) + if not bs.rstrip(_ALWAYS_SAFE_BYTES + safe): + return bs.decode() + try: + quoter = _safe_quoters[safe] + except KeyError as e: + _safe_quoters[safe] = quoter = Quoter(safe) + + res = "" + for char in bs: + res += quoter.get(char) + return res \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/vl53l0x.py b/mixly/boards/default/micropython/build/lib/vl53l0x.py new file mode 100644 index 00000000..093fba47 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/vl53l0x.py @@ -0,0 +1,350 @@ +""" +VL53L0X + +Micropython library for the VL53L0X +======================================================= + +#https://github.com/mcauser/deshipu-micropython-vl53l0x.git 20220216 + +dahanzimin From the Mixly Team +""" +from micropython import const +import ustruct +import utime + + +_IO_TIMEOUT = 1000 +_SYSRANGE_START = const(0x00) +_EXTSUP_HV = const(0x89) +_MSRC_CONFIG = const(0x60) +_FINAL_RATE_RTN_LIMIT = const(0x44) +_SYSTEM_SEQUENCE = const(0x01) +_SPAD_REF_START = const(0x4f) +_SPAD_ENABLES = const(0xb0) +_REF_EN_START_SELECT = const(0xb6) +_SPAD_NUM_REQUESTED = const(0x4e) +_INTERRUPT_GPIO = const(0x0a) +_INTERRUPT_CLEAR = const(0x0b) +_GPIO_MUX_ACTIVE_HIGH = const(0x84) +_RESULT_INTERRUPT_STATUS = const(0x13) +_RESULT_RANGE_STATUS = const(0x14) +_OSC_CALIBRATE = const(0xf8) +_MEASURE_PERIOD = const(0x04) + + +class TimeoutError(RuntimeError): + pass + + +class VL53L0X: + def __init__(self, i2c, address=0x29): + self.i2c = i2c + self.address = address + self.init() + self._started = False + + def _registers(self, register, values=None, struct='B'): + if values is None: + size = ustruct.calcsize(struct) + data = self.i2c.readfrom_mem(self.address, register, size) + values = ustruct.unpack(struct, data) + return values + data = ustruct.pack(struct, *values) + self.i2c.writeto_mem(self.address, register, data) + + def _register(self, register, value=None, struct='B'): + if value is None: + return self._registers(register, struct=struct)[0] + self._registers(register, (value,), struct=struct) + + def _flag(self, register=0x00, bit=0, value=None): + data = self._register(register) + mask = 1 << bit + if value is None: + return bool(data & mask) + elif value: + data |= mask + else: + data &= ~mask + self._register(register, data) + + def _config(self, *config): + for register, value in config: + self._register(register, value) + + def init(self, power2v8=True): + self._flag(_EXTSUP_HV, 0, power2v8) + + # I2C standard mode + self._config( + (0x88, 0x00), + + (0x80, 0x01), + (0xff, 0x01), + (0x00, 0x00), + ) + self._stop_variable = self._register(0x91) + self._config( + (0x00, 0x01), + (0xff, 0x00), + (0x80, 0x00), + ) + + # disable signal_rate_msrc and signal_rate_pre_range limit checks + self._flag(_MSRC_CONFIG, 1, True) + self._flag(_MSRC_CONFIG, 4, True) + + # rate_limit = 0.25 + self._register(_FINAL_RATE_RTN_LIMIT, int(0.25 * (1 << 7)), + struct='>H') + + self._register(_SYSTEM_SEQUENCE, 0xff) + + spad_count, is_aperture = self._spad_info() + spad_map = bytearray(self._registers(_SPAD_ENABLES, struct='6B')) + + # set reference spads + self._config( + (0xff, 0x01), + (_SPAD_REF_START, 0x00), + (_SPAD_NUM_REQUESTED, 0x2c), + (0xff, 0x00), + (_REF_EN_START_SELECT, 0xb4), + ) + + spads_enabled = 0 + for i in range(48): + if i < 12 and is_aperture or spads_enabled >= spad_count: + spad_map[i // 8] &= ~(1 << (i >> 2)) + elif spad_map[i // 8] & (1 << (i >> 2)): + spads_enabled += 1 + + self._registers(_SPAD_ENABLES, spad_map, struct='6B') + + self._config( + (0xff, 0x01), + (0x00, 0x00), + + (0xff, 0x00), + (0x09, 0x00), + (0x10, 0x00), + (0x11, 0x00), + + (0x24, 0x01), + (0x25, 0xFF), + (0x75, 0x00), + + (0xFF, 0x01), + (0x4E, 0x2C), + (0x48, 0x00), + (0x30, 0x20), + + (0xFF, 0x00), + (0x30, 0x09), + (0x54, 0x00), + (0x31, 0x04), + (0x32, 0x03), + (0x40, 0x83), + (0x46, 0x25), + (0x60, 0x00), + (0x27, 0x00), + (0x50, 0x06), + (0x51, 0x00), + (0x52, 0x96), + (0x56, 0x08), + (0x57, 0x30), + (0x61, 0x00), + (0x62, 0x00), + (0x64, 0x00), + (0x65, 0x00), + (0x66, 0xA0), + + (0xFF, 0x01), + (0x22, 0x32), + (0x47, 0x14), + (0x49, 0xFF), + (0x4A, 0x00), + + (0xFF, 0x00), + (0x7A, 0x0A), + (0x7B, 0x00), + (0x78, 0x21), + + (0xFF, 0x01), + (0x23, 0x34), + (0x42, 0x00), + (0x44, 0xFF), + (0x45, 0x26), + (0x46, 0x05), + (0x40, 0x40), + (0x0E, 0x06), + (0x20, 0x1A), + (0x43, 0x40), + + (0xFF, 0x00), + (0x34, 0x03), + (0x35, 0x44), + + (0xFF, 0x01), + (0x31, 0x04), + (0x4B, 0x09), + (0x4C, 0x05), + (0x4D, 0x04), + + (0xFF, 0x00), + (0x44, 0x00), + (0x45, 0x20), + (0x47, 0x08), + (0x48, 0x28), + (0x67, 0x00), + (0x70, 0x04), + (0x71, 0x01), + (0x72, 0xFE), + (0x76, 0x00), + (0x77, 0x00), + + (0xFF, 0x01), + (0x0D, 0x01), + + (0xFF, 0x00), + (0x80, 0x01), + (0x01, 0xF8), + + (0xFF, 0x01), + (0x8E, 0x01), + (0x00, 0x01), + (0xFF, 0x00), + (0x80, 0x00), + ) + + self._register(_INTERRUPT_GPIO, 0x04) + self._flag(_GPIO_MUX_ACTIVE_HIGH, 4, False) + self._register(_INTERRUPT_CLEAR, 0x01) + + # XXX Need to implement this. + #budget = self._timing_budget() + #self._register(_SYSTEM_SEQUENCE, 0xe8) + #self._timing_budget(budget) + + self._register(_SYSTEM_SEQUENCE, 0x01) + self._calibrate(0x40) + self._register(_SYSTEM_SEQUENCE, 0x02) + self._calibrate(0x00) + + self._register(_SYSTEM_SEQUENCE, 0xe8) + + def _spad_info(self): + self._config( + (0x80, 0x01), + (0xff, 0x01), + (0x00, 0x00), + + (0xff, 0x06), + ) + self._flag(0x83, 3, True) + self._config( + (0xff, 0x07), + (0x81, 0x01), + + (0x80, 0x01), + + (0x94, 0x6b), + (0x83, 0x00), + ) + for timeout in range(_IO_TIMEOUT): + if self._register(0x83): + break + utime.sleep_ms(1) + else: + raise TimeoutError() + self._config( + (0x83, 0x01), + ) + value = self._register(0x92) + self._config( + (0x81, 0x00), + (0xff, 0x06), + ) + self._flag(0x83, 3, False) + self._config( + (0xff, 0x01), + (0x00, 0x01), + + (0xff, 0x00), + (0x80, 0x00), + ) + count = value & 0x7f + is_aperture = bool(value & 0b10000000) + return count, is_aperture + + def _calibrate(self, vhv_init_byte): + self._register(_SYSRANGE_START, 0x01 | vhv_init_byte) + for timeout in range(_IO_TIMEOUT): + if self._register(_RESULT_INTERRUPT_STATUS) & 0x07: + break + utime.sleep_ms(1) + else: + raise TimeoutError() + self._register(_INTERRUPT_CLEAR, 0x01) + self._register(_SYSRANGE_START, 0x00) + + def start(self, period=0): + self._config( + (0x80, 0x01), + (0xFF, 0x01), + (0x00, 0x00), + (0x91, self._stop_variable), + (0x00, 0x01), + (0xFF, 0x00), + (0x80, 0x00), + ) + if period: + oscilator = self._register(_OSC_CALIBRATE, struct='>H') + if oscilator: + period *= oscilator + self._register(_MEASURE_PERIOD, period, struct='>H') + self._register(_SYSRANGE_START, 0x04) + else: + self._register(_SYSRANGE_START, 0x02) + self._started = True + + def stop(self): + self._register(_SYSRANGE_START, 0x01) + self._config( + (0xFF, 0x01), + (0x00, 0x00), + (0x91, self._stop_variable), + (0x00, 0x01), + (0xFF, 0x00), + ) + self._started = False + + def read(self): + if not self._started: + self._config( + (0x80, 0x01), + (0xFF, 0x01), + (0x00, 0x00), + (0x91, self._stop_variable), + (0x00, 0x01), + (0xFF, 0x00), + (0x80, 0x00), + (_SYSRANGE_START, 0x01), + ) + for timeout in range(_IO_TIMEOUT): + if not self._register(_SYSRANGE_START) & 0x01: + break + utime.sleep_ms(1) + else: + raise TimeoutError() + for timeout in range(_IO_TIMEOUT): + if self._register(_RESULT_INTERRUPT_STATUS) & 0x07: + break + utime.sleep_ms(1) + else: + raise TimeoutError() + value = self._register(_RESULT_RANGE_STATUS + 10, struct='>H') + self._register(_INTERRUPT_CLEAR, 0x01) + return value + + diff --git a/mixly/boards/default/micropython/build/lib/websocket.py b/mixly/boards/default/micropython/build/lib/websocket.py new file mode 100644 index 00000000..2d79c367 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/websocket.py @@ -0,0 +1,229 @@ +'''''' +import usocket as socket +import ubinascii as binascii +import urandom as random +import ustruct as struct +import urandom as random +from ucollections import namedtuple + +# Opcodes +OP_CONT = const(0x0) +OP_TEXT = const(0x1) +OP_BYTES = const(0x2) +OP_CLOSE = const(0x8) +OP_PING = const(0x9) +OP_PONG = const(0xA) + +# Close codes +CLOSE_OK = const(1000) +CLOSE_GOING_AWAY = const(1001) +CLOSE_PROTOCOL_ERROR = const(1002) +CLOSE_DATA_NOT_SUPPORTED = const(1003) +CLOSE_BAD_DATA = const(1007) +CLOSE_POLICY_VIOLATION = const(1008) +CLOSE_TOO_BIG = const(1009) +CLOSE_MISSING_EXTN = const(1010) +CLOSE_BAD_CONDITION = const(1011) + +URI = namedtuple('URI', ('protocol', 'hostname', 'port', 'path')) + +class NoDataException(Exception): + pass + +class ConnectionClosed(Exception): + pass + +def urlparse(uri): + # Split protocol and the rest + protocol, rest = uri.split('://', 1) + if '/' in rest: + hostname_port, path = rest.split('/', 1) + path = '/' + path + else: + hostname_port, path = rest, '' + if ':' in hostname_port: + hostname, port = hostname_port.rsplit(':', 1) + else: + hostname, port = hostname_port, None + if port is None: + port = 443 if protocol == 'wss' else 80 + return URI(protocol, hostname, port, path) + +class Websocket: + """Basis of the Websocket protocol.""" + + is_client = False + + def __init__(self, sock): + self.sock = sock + self.open = True + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + self.close() + + def settimeout(self, timeout): + self.sock.settimeout(timeout) + + def read_frame(self, max_size=None): + """Read a frame from the socket""" + # Frame header + two_bytes = self.sock.read(2) + if not two_bytes: + raise NoDataException + byte1, byte2 = struct.unpack('!BB', two_bytes) + # Byte 1: FIN(1) _(1) _(1) _(1) OPCODE(4) + fin = bool(byte1 & 0x80) + opcode = byte1 & 0x0F + # Byte 2: MASK(1) LENGTH(7) + mask = bool(byte2 & (1 << 7)) + length = byte2 & 0x7F + + if length == 126: # Magic number, length header is 2 bytes + (length,) = struct.unpack('!H', self.sock.read(2)) + elif length == 127: # Magic number, length header is 8 bytes + (length,) = struct.unpack('!Q', self.sock.read(8)) + if mask: # Mask is 4 bytes + mask_bits = self.sock.read(4) + try: + data = self.sock.read(length) + except MemoryError: + # We can't receive this many bytes, close the socket + self.close(code=CLOSE_TOO_BIG) + return True, OP_CLOSE, None + if mask: + data = bytes(b ^ mask_bits[i % 4] for i, b in enumerate(data)) + return fin, opcode, data + + def write_frame(self, opcode, data=b''): + """Write a frame to the socket""" + fin = True + mask = self.is_client # messages sent by client are masked + + length = len(data) + # Frame header + # Byte 1: FIN(1) _(1) _(1) _(1) OPCODE(4) + byte1 = 0x80 if fin else 0 + byte1 |= opcode + # Byte 2: MASK(1) LENGTH(7) + byte2 = 0x80 if mask else 0 + if length < 126: # 126 is magic value to use 2-byte length header + byte2 |= length + self.sock.write(struct.pack('!BB', byte1, byte2)) + elif length < (1 << 16): # Length fits in 2-bytes + byte2 |= 126 # Magic code + self.sock.write(struct.pack('!BBH', byte1, byte2, length)) + elif length < (1 << 64): + byte2 |= 127 # Magic code + self.sock.write(struct.pack('!BBQ', byte1, byte2, length)) + else: + raise ValueError() + if mask: # Mask is 4 bytes + mask_bits = struct.pack('!I', random.getrandbits(32)) + self.sock.write(mask_bits) + data = bytes(b ^ mask_bits[i % 4] for i, b in enumerate(data)) + self.sock.write(data) + + def recv(self): + """Receive data from the websocket""" + assert self.open + + while self.open: + try: + fin, opcode, data = self.read_frame() + except NoDataException: + return '' + except ValueError: + self._close() + raise ConnectionClosed() + + if not fin: + raise NotImplementedError() + + if opcode == OP_TEXT: + return data.decode('utf-8') + elif opcode == OP_BYTES: + return data + elif opcode == OP_CLOSE: + self._close() + return + elif opcode == OP_PONG: + # Ignore this frame, keep waiting for a data frame + continue + elif opcode == OP_PING: + # We need to send a pong frame + self.write_frame(OP_PONG, data) + # And then wait to receive + continue + elif opcode == OP_CONT: + # This is a continuation of a previous frame + raise NotImplementedError(opcode) + else: + raise ValueError(opcode) + + def send(self, buf): + """Send data to the websocket.""" + assert self.open + if isinstance(buf, str): + opcode = OP_TEXT + buf = buf.encode('utf-8') + elif isinstance(buf, bytes): + opcode = OP_BYTES + else: + raise TypeError() + self.write_frame(opcode, buf) + + def close(self, code=CLOSE_OK, reason=''): + """Close the websocket.""" + if not self.open: + return + buf = struct.pack('!H', code) + reason.encode('utf-8') + self.write_frame(OP_CLOSE, buf) + self._close() + + def _close(self): + self.open = False + self.sock.close() + +class WebsocketClient(Websocket): + is_client = True + +def connect(uri, headers=None): + """Connect a websocket.""" + uri = urlparse(uri) + assert uri + sock = socket.socket() + addr = socket.getaddrinfo(uri.hostname, uri.port) + sock.connect(addr[0][4]) + if uri.protocol == 'wss': + import ssl as ussl + sock = ussl.wrap_socket(sock, server_hostname=uri.hostname) + + def send_header(header, *args): + sock.write(header % args + '\r\n') + + # Sec-WebSocket-Key is 16 bytes of random base64 encoded + key = binascii.b2a_base64(bytes(random.getrandbits(8) for _ in range(16)))[:-1] + + send_header(b'GET %s HTTP/1.1', uri.path or '/') + send_header(b'Host: %s:%s', uri.hostname, uri.port) + send_header(b'Connection: Upgrade') + send_header(b'Upgrade: websocket') + send_header(b'Sec-WebSocket-Key: %s', key) + send_header(b'Sec-WebSocket-Version: 13') + send_header(b'Origin: http://{hostname}:{port}'.format(hostname=uri.hostname, port=uri.port)) + if headers: # 注入自定义头 + for k, v in headers.items(): + send_header((k + ": " + v).encode()) + send_header(b'') + + header = sock.readline()[:-2] + assert header.startswith(b'HTTP/1.1 101 '), header + # We don't (currently) need these headers + # FIXME: should we check the return key? + while header: + header = sock.readline()[:-2] + + return WebsocketClient(sock) diff --git a/mixly/boards/default/micropython/build/lib/ws2812.py b/mixly/boards/default/micropython/build/lib/ws2812.py new file mode 100644 index 00000000..abe6e783 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ws2812.py @@ -0,0 +1,84 @@ +""" +WS2812 RGB + +Micropython library for the WS2812 NeoPixel-RGB +======================================================= + +#Preliminary composition 20240110 + +dahanzimin From the Mixly Team +""" +from time import sleep +from machine import bitstream + +class NeoPixel: + def __init__(self, pin, n, bpp=3, timing=1, ORDER=(1, 0, 2, 3), default=None, multiplex=False, leds=0): + self.pin = pin + self.bpp = bpp + self.leds = leds + self.rgbs = n-leds + self.ORDER = ORDER + self.multiplex = multiplex + self.rgb_buf = bytearray(self.rgbs * bpp) + self.led_buf = bytearray(self.leds * bpp) + self.timing = (((350, 850, 800, 400) if timing else (800, 1700, 1600, 900)) if isinstance(timing, int) else timing) + if not self.multiplex: self.pin.init(self.pin.OUT,value=default) + self.write() + + def __len__(self): + return self.rgbs + + def __setitem__(self, n, v): + for i in range(self.bpp): + self.rgb_buf[n * self.bpp + self.ORDER[i]] = v[i] + + def __getitem__(self, n): + return tuple(self.rgb_buf[n* self.bpp + self.ORDER[i]] for i in range(self.bpp)) + + def led_set(self, n, v): + for i in range(self.bpp): + self.led_buf[n * self.bpp + self.ORDER[i]] = v[i] + + def led_get(self, n): + return tuple(self.led_buf[n * self.bpp + self.ORDER[i]] for i in range(self.bpp)) + + def fill(self, v): + for i in range(self.bpp): + j = self.ORDER[i] + while j < self.rgbs * self.bpp: + self.rgb_buf[j] = v[i] + j += self.bpp + + def write(self): + if self.multiplex: self.pin.init(self.pin.OUT) + bitstream(self.pin, 0, self.timing, self.rgb_buf + self.led_buf) + if self.multiplex: self.pin.init(self.pin.IN) + + def color_chase(self,R, G, B, wait): + for i in range(self.rgbs): + self.__setitem__(i,(R, G, B)) + self.write() + sleep(wait/1000) + + def rainbow_cycle(self, wait, clear=True): + for j in range(255): + for i in range(self.rgbs): + rc_index = (i * 256 // self.rgbs) + j + self.__setitem__(i,self.wheel(rc_index & 255)) + self.write() + sleep(wait / 1000 / 256) + if clear: + self.fill((0, 0, 0)) + self.write() + + def wheel(self,pos): + if pos < 0 or pos > 255: + return (0, 0, 0) + elif pos < 85: + return (pos * 3, 255 - pos * 3, 0) + elif pos < 170: + pos -= 85 + return (255 - pos * 3, 0, pos * 3) + else: + pos -= 170 + return (0, pos * 3, 255 - pos * 3) diff --git a/mixly/boards/default/micropython/build/lib/ws_lora.py b/mixly/boards/default/micropython/build/lib/ws_lora.py new file mode 100644 index 00000000..ff74b959 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ws_lora.py @@ -0,0 +1,129 @@ +""" +WS_Lora Weather Station + +Micropython library for Weather Station /Lora +======================================================= + +#Preliminary composition 20220408 + +dahanzimin From the Mixly Team +""" +from json import dumps +from rfm98 import RFM98 +from ubinascii import hexlify +from machine import I2C,SoftI2C,unique_id + +names =(("编号","电量","风速","阵风","风向","雨量","温度","湿度","光照","紫外线指数","气压","信号强度"), + ("ID","Battery","Wind Speed","Gust","Wind Direction","Rainfall","Temperature","Humidity","Illumination","UVI","Atmospheric","RSSI")) + +class Weather(RFM98): + def __init__(self,spi,cs_pin,i2c=None): + '''对继承初始化配置''' + super().__init__(spi,cs_pin,frequency_mhz=433.92,signal_bandwidth=125E3,coding_rate=5,spreading_factor=11) + self._data=(None,None,None,None,None,None,None,None,None,None,None,None,None) + self._atmos=None + self._labels=[] + + if type(i2c) in [I2C,SoftI2C]: + if 0x76 in i2c.scan(): + import hp203x + self._atmos = hp203x.HP203X(i2c) + + def _data_deal(self,buffer): + '''对解码数据进行处理''' + if self._crc8(buffer[0:14]) == buffer[14]: + Device_ID = (buffer[1] & 0x0f) <<4 | buffer[2] >>4 + State_BAT = (buffer[2] & 0x08) >>3 + AVG_Swind = (buffer[3] | (buffer[2] & 0x01)<<8)/10 + Gust_Swind = (buffer[4] | (buffer[2] & 0x02)<<7)/10 + DIR_wind = buffer[5] | (buffer[2] & 0x04)<<6 + SUM_Rain = (buffer[7] | buffer[6] <<8 )/10 + Temp_F = ((buffer[9] | (buffer[8] & 0x0F)<<8)-400)/10 + Temp_C = round((Temp_F-32)/1.8,2) + Humidity = buffer[10] + Light_Lux = (buffer[12] | buffer[11] <<8 | (buffer[8] & 0x30)<<12)/10 + UVI = buffer[13] / 10 + Pa = self._atmos.pressure() if self._atmos else None + #待添加数据值(Temp_F,Humidity,Light_Lux,UVI)报错处理 + return Device_ID,1-State_BAT,AVG_Swind,Gust_Swind,DIR_wind,SUM_Rain,Temp_C,Humidity,Light_Lux,UVI,Pa,super().packet_rssi(),super().packet_snr() + else: + return False + + def _crc8(self,buffer): + '''对数据进行CRC校验''' + crc = 0x00 + for byte in buffer: + crc ^= byte + for _ in range(8): + if crc & 0x80: + crc = (crc << 1) ^ 0x31 + else: + crc = crc << 1 + return crc & 0xff # return the bottom 8 bits + + def label(self,*args): + '''标记气象站标签如 (id,long,lat)''' + for arg in args: + if len(arg) == 3: + flag=True + for label in self._labels: + if label['ws_id'] == arg[0]: + label.update({'long':arg[1],'lat':arg[2]}) + flag=False + if flag: + self._labels.append({'ws_id':arg[0],'long':arg[1],'lat':arg[2]}) + else: + raise AttributeError('Invalid Input , format is (id,long,lat)') + return self._labels + + def any(self): + '''判读是否有数据''' + buffer=super().recv() + if buffer: + if (len(buffer)>=15) & (buffer[0] == 0xD4): + self._data=self._data_deal(buffer) + return True + + def data(self,chinese=True): + '''获取气象数据''' + _name=names[0] if chinese else names[1] + info_dict={_name[0]:self._data[0], + _name[1]:"Normal" if self._data[1]==1 else "Low", + _name[2]:str(self._data[2])+'m/s', + _name[3]:str(self._data[3])+'m/s', + _name[4]:str(self._data[4])+'°', + _name[5]:str(self._data[5])+'mm', + _name[6]:str(self._data[6])+'℃', + _name[7]:str(self._data[7])+'%', + _name[8]:str(self._data[8])+'lux', + _name[9]:self._data[9], + _name[10]:str(self._data[10])+'hPa', + _name[11]:str(self._data[11])+'dBm'} + + for label in self._labels: + if label['ws_id'] == self._data[0]: + msg_list=[] + for info in info_dict: + msg_list.append({"label":info,"value":info_dict[info]}) + label_dict={"message":msg_list,'clientid':hexlify(unique_id())} + label_dict.update(label) + return self._data,dumps(info_dict),dumps(label_dict) + return self._data,dumps(info_dict),'null' + + def uart_mixio(self,topic="station"): + '''打包气象数据串口转发''' + info_dict={topic+"-"+str(self._data[0]): + {"电量":"正常" if self._data[1]==1 else "亏电", + "风速":self._data[2], + "阵风":self._data[3], + "风向":self._data[4], + "雨量":self._data[5], + "温度":self._data[6], + "湿度":self._data[7], + "光照":self._data[8], + "紫外线":self._data[9], + "大气压":self._data[10], + "信号强度":self._data[11]}} + + print(dumps(info_dict)) + return info_dict \ No newline at end of file diff --git a/mixly/boards/default/micropython/build/lib/ws_solo.py b/mixly/boards/default/micropython/build/lib/ws_solo.py new file mode 100644 index 00000000..bd742ce7 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/ws_solo.py @@ -0,0 +1,138 @@ +""" +Weather_Solo + +Micropython library for the Weather_Solo(WIND & RAIN) +======================================================= + +#Preliminary composition 20231207 + +@dahanzimin From the Mixly Team +""" +import time +import math +from machine import Pin, ADC + +class Weather_WS: + + def __init__(self, pin, leaf=0.09, pulse=2): + Pin(pin, Pin.IN).irq(handler=self._ws_func, trigger=Pin.IRQ_FALLING) + self._wtime = time.ticks_ms() + self._distance = 2 * math.pi * leaf / pulse + self._pulse = 0 + + def _ws_func(self, pin): + if pin.value() == 0: + self._pulse += self._distance + + def _grade(self, speed): + if speed <= 0.2: + grade=0 + elif speed <=1.5: + grade=1 + elif speed <=3.3: + grade=2 + elif speed <=5.4: + grade=3 + elif speed <=7.9: + grade=4 + elif speed <=10.7: + grade=5 + elif speed <=13.8: + grade=6 + elif speed <=17.1: + grade=7 + elif speed <=20.7: + grade=8 + elif speed <=24.4: + grade=9 + elif speed <=28.4: + grade=10 + elif speed <=32.6: + grade=11 + else: + grade=12 + return grade + + def wind_speed(self): + time.sleep_ms(100) + speed = self._pulse / time.ticks_diff(time.ticks_ms(), self._wtime) * 1000 if self._pulse > 0 else 0 + self._wtime = time.ticks_ms() + self._pulse = 0 + return round(speed, 2), self._grade(speed) + +class Weather_WD: + + _DS = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"] + _DA = [0, 22.5, 45, 67.5, 90, 112.5, 135, 157.5, 180, 202.5, 225, 247.5, 270, 292.5, 315, 337.5] + + def __init__(self, pin): + self.adc = ADC(Pin(pin), atten=ADC.ATTN_11DB) + + def wind_direction(self): + values = [] + for _ in range(20): + values.append(self.adc.read_uv()/1000000) + time.sleep_ms(1) + ain = sum(values) / 20 + + if ain <=0.083: + dir=12 + elif ain <=0.135: + dir=14 + elif ain <=0.184: + dir=13 + elif ain <=0.253: + dir=0 + elif ain <=0.349: + dir=15 + elif ain <=0.421: + dir=10 + elif ain <=0.568: + dir=11 + elif ain <=0.761: + dir=2 + elif ain <=1.004: + dir=1 + elif ain <=1.273: + dir=8 + elif ain <=1.501: + dir=9 + elif ain <=1.826: + dir=6 + elif ain <=2.137: + dir=7 + elif ain <=2.308: + dir=4 + elif ain <=2.429: + dir=3 + else: + dir=5 + return self._DS[dir], self._DA[dir] + +class Weather_Rain: + + def __init__(self, pin, capacity=0.2794): + Pin(pin, Pin.IN).irq(handler=self._rain_func, trigger=Pin.IRQ_FALLING) + self._rtime = time.ticks_ms() + self._load = capacity + self._mean = 0 + self._count = 0 + + def _rain_func(self, pin): + if pin.value() == 0: + self._count += self._load + + def rain_count(self, time_s=3600): + if time.ticks_diff(time.ticks_ms(), self._rtime) // 1000 >= time_s: + self._mean = self._count / time.ticks_diff(time.ticks_ms(), self._rtime) * time_s * 1000 if self._count > 0 else 0 + self._rtime = time.ticks_ms() + self._count = 0 + return round(self._count, 2), round(self._mean, 4) + +#integration +class Weather_Solo(Weather_WD, Weather_WS, Weather_Rain): + + def __init__(self, pin_wd, pin_ws, pin_rain): + Weather_WD.__init__(self, pin_wd) + Weather_WS.__init__(self, pin_ws) + Weather_Rain.__init__(self, pin_rain) diff --git a/mixly/boards/default/micropython/build/lib/xunfei.py b/mixly/boards/default/micropython/build/lib/xunfei.py new file mode 100644 index 00000000..19e62428 --- /dev/null +++ b/mixly/boards/default/micropython/build/lib/xunfei.py @@ -0,0 +1,286 @@ +""" +MINI_XUNFEI + +Micropython library for the MIC_ADC XUNFEI(ASR, LLM) +======================================================= +@dahanzimin From the Mixly Team + +""" +import time +import hmac +import json +import hashlib +import rtctime +import websocket +import adc_mic +from base64 import b64decode, b64encode +from urllib import urlencode, urlparse + +class Ws_Param: + def __init__(self, APPID, APIKey, APISecret, Spark_url): + self.APPID = APPID + self.APIKey = APIKey + self.APISecret = APISecret + self.url = Spark_url + self.urlparse = urlparse(Spark_url) + + def create_url(self): + date = rtctime.rfc1123_time() + signature_origin = "host: " + self.urlparse.netloc + "\n" + signature_origin += "date: " + date + "\n" + signature_origin += "GET " + self.urlparse.path + " HTTP/1.1" + signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'), digestmod=hashlib.sha256).digest() + signature_base64 = b64encode(signature_sha).decode('utf-8') + authorization_origin = ('api_key="{}", algorithm="hmac-sha256", headers="host date request-line", signature="{}"'.format(self.APIKey, signature_base64)) + authorization = b64encode(authorization_origin.encode('utf-8')).decode('utf-8') + headers = {"authorization": authorization, "date": date, "host": self.urlparse.netloc} + return self.url + '?' + urlencode(headers) + +#语音听写 +class ASR_WebSocket(Ws_Param): + def __init__(self, adcpin, APPID, APIKey, APISecret, url='ws://iat-api.xfyun.cn/v2/iat', sample_rate=8000): + super().__init__(APPID, APIKey, APISecret, url) + self.ws = None + self.rate = sample_rate + self.mic = adc_mic.ADCMic(adcpin, sample_rate=sample_rate) + self.business = { + "domain": "iat", + "language": "zh_cn", + "accent": "mandarin", + "vad_eos": 1000, + "nbest": 1, + "wbest": 1, + } + + def connect(self): + self.ws = websocket.connect(self.create_url()) + self.ws.settimeout(1000) + + def _frame(self, status, buf): + if status == 0: + return {"common": {"app_id": self.APPID}, "business": self.business, "data": {"status": status, "format": f"audio/L16;rate={self.rate}", "audio": str(b64encode(buf), 'utf-8'), "encoding": "raw"}} + else: + return {"data": {"status": status, "format": f"audio/L16;rate={self.rate}", "audio": str(b64encode(buf), 'utf-8'), "encoding": "raw"}} + + def on_message(self, message): + result = "" + msg = json.loads(message) + code = msg["code"] + if code != 0: + raise AttributeError("%s Code:%s" % (msg["message"], code)) + else: + data = msg["data"]["result"]["ws"] + for i in data: + for w in i["cw"]: + result += w["w"] + if msg["data"]["status"]== 2: + return result, False + return result, True + + def receive_messages(self): + msg = "" + while True: + t = self.on_message(self.ws.recv()) + msg += t[0] + if not t[1]: + break + return msg + + def run(self, seconds=3, pace=True): + try: + self.connect() + _state = 0 + ibuf = int(self.rate * 0.2) + _buf = bytearray(ibuf) + _size = int(ibuf * seconds * 10) #100ms/次 + self.mic.start() + if pace: print('[',end ="") + while _size > 0: + if self.mic.read_into(_buf): + _size -= ibuf + if pace: print('=',end ="") + # 第一帧处理 + if _state == 0: + d = self._frame(_state, _buf) + _state = 1 + # 中间帧处理 + else: + d = self._frame(_state, _buf) + self.ws.send(json.dumps(d)) + # 最后一帧处理 + self.mic.stop() + d = self._frame(2, b'\x00') + self.ws.send(json.dumps(d)) + if pace: print(']') + msg = self.receive_messages() + return msg + except Exception as e: + onboard_bot.pcm_en(False) #PCM关闭 + if "403 Forbidden" in str(e): + raise OSError("Access denied, Please try updating clock time") + else: + print("Run error: %s" % (e)) + finally: + self.mic.stop() + self.ws.close() + +#中英识别大模型 +class IAT_WebSocket(ASR_WebSocket): + def __init__(self, adcpin, APPID, APIKey, APISecret, url='ws://iat.xf-yun.com/v1', sample_rate=8000, accent="mandarin", res_id=None): + super().__init__(adcpin, APPID, APIKey, APISecret, url, sample_rate) + self.res_id = res_id + self.business = { + "domain": "slm", + "language": "zh_cn", + "accent": accent, + "result": { + "encoding": "utf8", + "compress": "raw", + "format": "plain" + } + } + + def _frame(self, status, buf): + if status == 0: + return {"header": {"status": status, "app_id": self.APPID, "res_id": self.res_id}, "parameter": {"iat": self.business}, "payload": {"audio": { "audio": str(b64encode(buf), 'utf-8'), "sample_rate": self.rate, "encoding": "raw"}}} + else: + return {"header": {"status": status, "app_id": self.APPID, "res_id": self.res_id}, "payload": {"audio": { "audio": str(b64encode(buf), 'utf-8'), "sample_rate": self.rate, "encoding": "raw"}}} + + def on_message(self, message): + result = "" + msg = json.loads(message) + code = msg['header']["code"] + if code != 0: + raise AttributeError("%s Code:%s" % (msg['header']["message"], code)) + else: + if "payload" in msg: + text = msg["payload"]["result"]["text"] + data = json.loads(b64decode(text).decode())['ws'] + for i in data: + for w in i["cw"]: + result += w["w"] + if msg["header"]["status"]== 2: + return result, False + return result, True + +#大模型 +class LLM_WebSocket(Ws_Param): + Model_url = { + "Spark Ultra-32K": ("ws://spark-api.xf-yun.com/v4.0/chat", "4.0Ultra"), + "Spark Max-32K": ("ws://spark-api.xf-yun.com/chat/max-32k", "max-32k"), + "Spark Max": ("ws://spark-api.xf-yun.com/v3.5/chat", "generalv3.5"), + "Spark Pro-128K": (" ws://spark-api.xf-yun.com/chat/pro-128k", "pro-128k"), + "Spark Pro": ("ws://spark-api.xf-yun.com/v3.1/chat", "generalv3"), + "Spark Lite": ("ws://spark-api.xf-yun.com/v1.1/chat", "lite"), + "Spark kjwx": ("ws://spark-openapi-n.cn-huabei-1.xf-yun.com/v1.1/chat_kjwx", "kjwx"), + "Spark X1-32K": ("ws://spark-api.xf-yun.com/v1/x1", "x1"), + "Spark Customize": ("ws://sparkcube-api.xf-yun.com/v1/customize", "max"), + } + + def __init__(self, APPID, APIKey, APISecret, model='Spark Ultra-32K', system="你是知识渊博的助理,习惯简短表达", answers=50): + self.ws = None + self.answers = answers + self._url = self.Model_url[model] if model in self.Model_url else model + super().__init__(APPID, APIKey, APISecret, self._url[0]) + self._function = [{}, []] #[回调函数, 功能描述] + self._messages = [{"role": "system", "content": system}] + + def connect(self): + self.ws = websocket.connect(self.create_url()) + self.ws.settimeout(1000) + + def _params(self): + d = { + "header": {"app_id": self.APPID}, + "parameter": { + "chat": { + "domain": self._url[1], + "random_threshold": 0.5, + "max_tokens": 2048, + "auditing": "default" + } + }, + "payload": { + "message": { + "text": self._messages + } + } + } + if self._function[1]: + d["payload"]["functions"] = {"text": self._function[1]} + self.ws.send(json.dumps(d)) + + def function_call(self, callback, name, description, params): + """功能回调名称, 描述, ((参数名, 类型, 描述), ...)""" + properties = {"type": "object", "properties":{}, "required":[]} + for arg in params: + if len(arg) >= 3: + properties["properties"][arg[0]] = {"type": arg[1], "description": arg[2]} + if arg[0] not in properties["required"]: + properties["required"].append(arg[0]) + else: + raise AttributeError('Invalid Input , format is (name, type, description)') + self._function[0][name] = callback + self._function[1].append({"name": name, "description": description, "parameters": properties}) + + def empty_history(self): + self._messages = [] + + def add_history(self, role, content): + self._messages.append({ + "role": role, + "content": content + }) + + def on_message(self, message, reas): + result = "" + msg = json.loads(message) + code = msg['header']['code'] + if code != 0: + raise AttributeError("%s Code:%s" % (msg["header"]["message"], code)) + else: + choices = msg["payload"]["choices"] + text = choices["text"][0] + #推理 + if "reasoning_content" in text and reas: + print("reasoning: ", text["reasoning_content"]) + #回调 + if "tool_calls" in text: + function = text['tool_calls'][0]['function'] + if str(function['name']) in self._function[0] and function['arguments']: + self._function[0][function['name']](json.loads(function['arguments'])) + if "function_call" in text: + if str(text['function_call']['name']) in self._function[0] and text['function_call']['arguments']: + self._function[0][text['function_call']['name']](json.loads(text['function_call']['arguments'])) + #答复 + if "content" in text: + result += text["content"] + if choices["status"] == 2: + return result, False + return result, True + + def receive_messages(self, reas): + msg = "" + while True: + t = self.on_message(self.ws.recv(), reas) + msg += t[0] + if not t[1]: + break + return msg + + def run(self, question, reas=True): + try: + self.connect() + self.add_history("user", question) + self._params() + while self.answers < len(self._messages): + del self._messages[0] + msg = self.receive_messages(reas) + return msg + except Exception as e: + if "403 Forbidden" in str(e): + raise OSError("Access denied, Please try updating clock time") + else: + print("Run error: %s" % (e)) + finally: + self.ws.close() diff --git a/mixly/boards/default/micropython/index.xml b/mixly/boards/default/micropython/index.xml new file mode 100644 index 00000000..e69de29b diff --git a/mixly/boards/default/micropython/main.bundle.31d6cfe0.js b/mixly/boards/default/micropython/main.bundle.31d6cfe0.js new file mode 100644 index 00000000..e69de29b diff --git a/mixly/boards/default_src/micropython/.npmignore b/mixly/boards/default_src/micropython/.npmignore new file mode 100644 index 00000000..21ab2a3e --- /dev/null +++ b/mixly/boards/default_src/micropython/.npmignore @@ -0,0 +1,3 @@ +node_modules +build +origin \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/actuator.js b/mixly/boards/default_src/micropython/blocks/actuator.js new file mode 100644 index 00000000..57e341cb --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/actuator.js @@ -0,0 +1,482 @@ +import * as Blockly from 'blockly/core'; + +const ACTUATOR_HUE = 100; + +//Servo +export const servo_move = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput("DEGREE", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DEGREE_0_180); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SERVO_MOVE); + } +}; + +//LED +export const number = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["1", "1"], + ["2", "2"] + ]), 'op') + this.setOutput(true); + } +}; + +export const ledswitch = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_ON, "1"], + [Blockly.Msg.MIXLY_ESP32_OFF, "0"], + [Blockly.Msg.MIXLY_ESP32_TOGGLE, "-1"] + ]), "flag"); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const actuator_extern_led_bright = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING) + .appendField(Blockly.Msg.MIXLY_EXTERN_LED) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_EXTERN_LED_SETONOFF); + } +}; + +export const actuator_extern_get_led_bright = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.MIXLY_EXTERN_LED) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_EXTERN_LED_GETONOFF); + } +}; + +export const actuator_extern_led_brightness = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING) + .appendField(Blockly.Msg.MIXLY_EXTERN_LED) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_EXTERN_LED_SETBRIGHT); + } +}; + +export const actuator_led_bright = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_SETONOFF); + } +}; + +export const actuator_get_led_bright = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + +export const actuator_led_brightness = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_SETBRIGHT); + } +}; + +//music +export const esp32_music_pitch = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_TONE) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE); + } +}; + +export const esp32_music_pitch_with_time = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_TONE) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_DURATION); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE2); + } +}; + +export const esp32_music_stop = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_NOTONE) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const esp32_music_set_tempo = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput('TICKS') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_SET_TEMPO) + .appendField(Blockly.Msg.MICROBIT_ACTUATOR_ticks); + this.appendValueInput('BPM') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_SET_TEMPO); + } +} + +export const esp32_music_get_tempo = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Get_current_tempo) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_GET_TEMPO); + } +} + +export const esp32_music_reset = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_music) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_RESET); + } +} + +export const esp32_onboard_music_pitch = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TONE); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE); + } +}; + +export const esp32_onboard_music_pitch_with_time = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TONE); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_DURATION); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE2); + } +}; + +export const esp32_onboard_music_stop = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_NOTONE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const esp32_onboard_music_play_list = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS); + + } +} + +export const esp32_music_play_list = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS) + this.appendValueInput('PIN') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_PIN); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS); + + } +} + +export const esp32_mixgo_music_play_list_show = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS) + this.appendValueInput('PIN') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_PIN); + // this.appendValueInput('DISPLAY') + // .appendField(Blockly.Msg.MIXLY_ESP32_MIXGO_MUSIC_SHOW_IN); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MIXGO_MUSIC_PLAY_TONE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAYSHOW) + } +} +//RGB +export const actuator_neopixel_init = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP) + .setCheck("var"); + this.appendValueInput("PIN", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PIN); + this.appendValueInput("LEDCOUNT") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_COUNT); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_RGB_PIN_COUNT); + } +}; + +export const actuator_neopixel_rgb = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput('SUB') + .setCheck("var"); + // .appendField(Blockly.Msg.MIXLY_SETUP) + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B); + } +}; + +export const actuator_neopixel_write = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_RGB_WRITE) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_WRI); + } +}; + +export const actuator_onboard_neopixel_rgb = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B); + } +}; + +export const actuator_onboard_neopixel_rgb_all = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B); + } +}; + +export const actuator_onboard_neopixel_write = { + init: function () { + this.setColour(ACTUATOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_RGB_WRITE) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_WRI); + } +}; + + +export const led_light = actuator_led_bright; +export const get_led_bright = actuator_get_led_bright; +export const led_brightness = actuator_led_brightness; diff --git a/mixly/boards/default_src/micropython/blocks/actuator_extern.js b/mixly/boards/default_src/micropython/blocks/actuator_extern.js new file mode 100644 index 00000000..d9a56bcb --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/actuator_extern.js @@ -0,0 +1,1211 @@ +import * as Blockly from 'blockly/core'; +import { Profile } from 'mixly'; + +const ACTUATOR_EXTERN_HUE = '#74A55B'; + +//music +export const esp32_music_pitch_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MIDI) + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP) + .setCheck("var"); + this.appendValueInput("PIN", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PIN); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_RGB_PIN_COUNT); + } +}; + +export const esp32_music_pitch = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_TONE) + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE); + } +}; + +export const esp32_music_pitch_with_time = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_TONE) + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_DURATION); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE2); + } +}; + +export const esp32_music_play_list = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS); + + } +} + +export const backstage_esp32_music_play_list = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_BACKSTAGE + Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_BACKSTAGE + Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS); + + } +} + +export const esp32_music_set_tempo_extern = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendValueInput('TICKS') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_SET_TEMPO) + .appendField(Blockly.Msg.MICROBIT_ACTUATOR_ticks); + this.appendValueInput('BPM') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_SET_TEMPO); + } +} + +export const esp32_music_get_tempo_extern = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Get_current_tempo) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_GET_TEMPO); + } +} + +export const esp32_music_reset_extern = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_music) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_RESET); + } +} + +export const esp32_music_stop = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_NOTONE) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const esp32_set_music_volume ={ + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + this.appendValueInput('percent') + .appendField(Blockly.Msg.MIXLY_MUSIC_VOLUME_SET); + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const actuator_extern_led_bright = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING) + .appendField(Blockly.Msg.MIXLY_EXTERN_LED) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_EXTERN_LED_SETONOFF); + } +}; + +export const actuator_extern_get_led_bright = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.MIXLY_EXTERN_LED) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_EXTERN_LED_GETONOFF); + } +}; + +export const actuator_extern_get_led_state = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.MIXLY_EXTERN_LED) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_EXTERN_LED_GETONOFF); + } +}; + +export const actuator_extern_led_brightness = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING) + .appendField(Blockly.Msg.MIXLY_EXTERN_LED) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.appendDummyInput() + .appendField('%') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_EXTERN_LED_SETBRIGHT); + } +}; + +//Servo +export const servo_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_SERVO) + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const servo_move = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput("DEGREE", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DEGREE_0_180); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SERVO_MOVE); + } +}; + +export const servo_speed_360 = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("VAR") + .appendField("360°" + Blockly.Msg.MIXLY_SERVO) + this.appendValueInput("SPEED", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.blockpy_turtle_rotate + Blockly.Msg.MIXLY_SPEED + " (-10~10)"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SERVO_360_TOOLTIP); + } +}; + +//Servo +export const servo_set_angle = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField('180°' + Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput("NUM", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SERVO_MOVE); + } +}; + +export const servo_set_speed = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField('360°' + Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendValueInput("NUM", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SERVO_SPEED_TOOLIPS); + } +}; + +export const servo_get_angle = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField('180°' + Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const servo_get_speed = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField('360°' + Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_SPEED); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const actuator_ms32006_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("初始化") + .setCheck("var"); + this.appendDummyInput() + .appendField("电机驱动"); + this.appendDummyInput() + .appendField("地址") + .appendField(new Blockly.FieldDropdown([['A', 'ms32006.ADDRESS_A'], ['B', 'ms32006.ADDRESS_B']]), 'mode'); + this.appendValueInput('SUB1') + .setCheck("var") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField("通信"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip("初始化MS32006电机驱动,使用I2C通信"); + } +}; + +export const actuator_ms32006_dcmotor = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("直流电机") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, "ms32006.MOT_CW"], + [Blockly.Msg.ANTI_CLOCKWISE, "ms32006.MOT_CCW"], + [Blockly.Msg.MOTOR_N, "ms32006.MOT_N"], + [Blockly.Msg.MOTOR_P, "ms32006.MOT_P"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip("设置直流电机的状态及转速(0-100)"); + } +}; + + + +export const actuator_ms32006_stepper = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("步进电机") + .setCheck("var"); + this.appendDummyInput() + .appendField("选择") + .appendField(new Blockly.FieldDropdown([['A', 'ms32006.MOT_A'], ['B', 'ms32006.MOT_B']]), 'mode'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, "ms32006.MOT_CW"], + [Blockly.Msg.ANTI_CLOCKWISE, "ms32006.MOT_CCW"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField("转速"); + this.appendValueInput('steps') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField("步数"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip("设置步进电机的状态、转速、步数(0-2047)"); + } +}; + +//rgb +export const actuator_neopixel_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP) + .setCheck("var"); + this.appendValueInput("PIN", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PIN); + this.appendValueInput("LEDCOUNT") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_COUNT); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_RGB_PIN_COUNT); + } +}; + +export const actuator_neopixel_rgb = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendValueInput('SUB') + .setCheck("var"); + // .appendField(Blockly.Msg.MIXLY_SETUP) + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MP); + } +}; + +export const actuator_neopixel_rgb_all = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_ALL_R_G_B_MIXGOCC); + } +}; + +export const actuator_neopixel_write = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_RGB_WRITE) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_WRI); + } +}; + +export const actuator_neopixel_rgb_show_all_rainbow = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RAINBOW); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_DURATION) + .appendField(Blockly.Msg.MIXLY_MILLIS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + } +}; + +export const actuator_neopixel_rgb_show_all_chase = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_CHASE); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.PYTHON_RANGE_STEP) + .appendField(Blockly.Msg.MIXLY_MILLIS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + } +}; + +export const actuator_use_uart_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "uart") + .appendField(new Blockly.FieldDropdown([ + ["uart1", "uart1"], + ["uart2", "uart2"] + ]), "key"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + ['SYN6288' + Blockly.Msg.MIXLY_AipSpeech_synthesis, 'SYN6288'], + ['NS9300' + Blockly.Msg.MIXLY_MUSIC_PLAYER, 'NS9300'] + ]), 'key2'); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const player_whether_stop = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_MUSIC_PLAYER) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_WHETHER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_STOPPED, "0"], + [Blockly.Msg.MIXLY_PLAYING, "1"], + [Blockly.Msg.MIXLY_PAUSED, "2"] + ]), "key"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const player_set_play = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MUSIC_PLAYER) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_STAT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MP3_PLAY, "1"], + [Blockly.Msg.MIXLY_MP3_PAUSE, "2"], + [Blockly.Msg.MIXLY_STOP, "3"], + [Blockly.Msg.MIXLY_MP3_PREV, "4"], + [Blockly.Msg.MIXLY_MP3_NEXT, "5"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const player_set_volume = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MUSIC_PLAYER) + .setCheck("var"); + this.appendValueInput('volume') + .appendField(Blockly.Msg.MIXLY_MP3_VOL + Blockly.Msg.MIXLY_STAT); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_PLAYER_SET_VOLUME_TOOLTIP); + } +} + +export const player_set_mode = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MUSIC_PLAYER) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MODE + Blockly.Msg.MIXLY_STAT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MP3_LOOP_ALL, "0"], + [Blockly.Msg.MIXLY_MP3_LOOP_ONE, "1"], + [Blockly.Msg.MIXLY_PLAYER_DIRECTORY_LOOP, "2"], + [Blockly.Msg.MIXLY_MP3_LOOP_RAM, "3"], + [Blockly.Msg.MIXLY_PLAYER_SINGLE_STOP, "4"], + [Blockly.Msg.MIXLY_PLAYER_SEQUENTIAL_PLAY, "5"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const player_play_music = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MUSIC_PLAYER) + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_START_MELODY, "play"], + [Blockly.Msg.MIXLY_PLAYER_INSERT_MUSIC, "insert"] + ]), "key"); + this.appendValueInput('song'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_PLAYER_PLAY_MUSIC_TOOTIP) + } +} + +export const player_insert_music = { + +} + +export const syn6288_set_voice = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField('SYN6288') + this.appendValueInput('VOICE') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SET_VOLUME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SET_VOLUME_TOOLTIP); + } +} + +export const syn6288_get_voice = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField('SYN6288') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_VOLUME) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SET_VOLUME_TOOLTIP); + } +} + +export const syn6288_builtin_voice = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField('SYN6288') + this.appendValueInput('VOICE') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_PLAY_HINTS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PROGRAM_BLOCK) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_TRUE, 'True'], [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_FALSE, 'False']]), 'mode'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_PLAY_HINTS_TOOLTIP); + } +} + +export const syn6288_tts_play = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField('SYN6288') + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_AipSpeech_synthesis); + this.appendValueInput('VOICE') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_BACKGROUND_MUSIC); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PROGRAM_BLOCK) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_TRUE, 'True'], [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_FALSE, 'False']]), 'mode'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_PLAY_TTS_TOOLTIP); + } +} + + +//mixbot extern +export const mixbot_addr_extern = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.extern_addr), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const robot_motor_extern = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_MOTOR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.appendDummyInput() + .appendField('%') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_MOTOR_EXTERN_TOOLTIP); + } +} + +export const robot_motor_extern_get_speed = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_MOTOR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_SPEED); + this.setOutput(true, Number); + this.setInputsInline(true); + } +} + +export const robot_traffic_light_extern = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_TRAFFIC_LIGHT) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_Turn_off_display, '0'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT_RED_ON, '1'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT_RED_BLINK, '2'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT_YELLOW_ON, '3'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT_YELLOW_BLINK, '4'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT_GREEN_ON, '5'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT_GREEN_BLINK, '6'] + ]), "light"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const robot_led_extern = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_WHITE, 'W'], + [Blockly.Msg.COLOUR_RGB_RED, 'R'], + [Blockly.Msg.COLOUR_RGB_YELLOW, 'Y'], + [Blockly.Msg.COLOUR_RGB_GREEN, 'G'], + [Blockly.Msg.COLOUR_RGB_BLUE, 'B'] + ]), "color") + .appendField("LED") + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendValueInput('value') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.BRIGHTNESS); + this.appendDummyInput() + .appendField('%') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const robot_led_extern_get_value = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_WHITE, 'W'], + [Blockly.Msg.COLOUR_RGB_RED, 'R'], + [Blockly.Msg.COLOUR_RGB_YELLOW, 'Y'], + [Blockly.Msg.COLOUR_RGB_GREEN, 'G'], + [Blockly.Msg.COLOUR_RGB_BLUE, 'B'] + ]), "color") + .appendField("LED") + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.BRIGHTNESS) + this.setOutput(true, Number); + this.setInputsInline(true); + } +} + +export const robot_servo_extern_get_status = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_SERVO_MOTOR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER, '[0]'], + [Blockly.Msg.MIXLY_SPEED, '[1]'], + [Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, '[2]'], + [Blockly.Msg.MIXLY_RELATIVE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, '[3]'], + [Blockly.Msg.MIXLY_MIXBOT_SERVO_BLOCK_OR_NOT, '[4]'], + [Blockly.Msg.MIXLY_MIXBOT_SERVO_FINISH_OR_NOT, '[5]'], + [Blockly.Msg.MIXLY_ALL, ''] + ]), "status"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +} + +export const robot_servo_extern_stop_mode = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_SERVO_MOTOR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_SERVO_SET_STOP_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MIXBOT_SERVO_STOP_MODE_KEEP, '0'], + [Blockly.Msg.MIXLY_MIXBOT_SERVO_STOP_MODE_COAST, '1'], + [Blockly.Msg.MIXLY_MIXBOT_SERVO_STOP_MODE_BRAKE, '2'] + ]), "status"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const robot_servo_extern_stop = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_SERVO_MOTOR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_STOP) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const robot_servo_extern_absolute_run = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_SERVO_MOTOR) + .appendField(Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + Blockly.Msg.MSG.run) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MODE) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SPEED + Blockly.Msg.MIXLY_MODE, '0'], + [Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER + Blockly.Msg.MIXLY_MODE, '1'] + ]), "status"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField('%') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_SERVO_TURN_DIRECTION) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, '0'], + [Blockly.Msg.MIXLY_MIXBOT_SERVO_NEAREST_PATH, '1'], + [Blockly.Msg.ANTI_CLOCKWISE, '2'] + ]), "direction"); + this.appendValueInput('angle') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DISPLAY_MATRIX_ROTATE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_SERVO_ABSOLUTE_ANGLE_TOOLTIP); + } +} + +export const robot_servo_extern_relative_origin = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_SERVO_MOTOR) + .appendField(Blockly.Msg.MIXLY_RELATIVE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + Blockly.Msg.MSG.run) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_SERVO_RELATIVE_ORIGIN_PATH) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const robot_servo_extern_relative_run = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_SERVO_MOTOR) + .appendField(Blockly.Msg.MIXLY_RELATIVE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + Blockly.Msg.MSG.run) + .appendField("(" + Blockly.Msg.MIXLY_MIXBOT_SERVO_LIKE_ENCODING_MOTOR + ")") + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MODE) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SPEED + Blockly.Msg.MIXLY_MODE, '0'], + [Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER + Blockly.Msg.MIXLY_MODE, '1'] + ]), "status"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField('%') + this.appendValueInput('angle') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DISPLAY_MATRIX_ROTATE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_SERVO_RELATIVE_ANGLE_TOOLTIP); + } +} + +export const robot_servo_extern_relative_continue = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_SERVO_MOTOR) + .appendField(Blockly.Msg.MIXLY_RELATIVE + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + Blockly.Msg.MSG.run) + .appendField("(" + Blockly.Msg.MIXLY_MIXBOT_SERVO_LIKE_ORDINARY_MOTOR + ")") + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_LEFT, "0"], [Blockly.Msg.MIXLY_RIGHT, "1"]]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MODE) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SPEED + Blockly.Msg.MIXLY_MODE, '0'], + [Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER + Blockly.Msg.MIXLY_MODE, '1'] + ]), "status"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField('%') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_SERVO_TURN_DIRECTION) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, '0'], + [Blockly.Msg.ANTI_CLOCKWISE, '2'] + ]), "direction"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const mixbot_actuator_extern_get_addr = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXBOT) + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MOTOR, 'ext_motor'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT, 'ext_traffic'], + [Blockly.Msg.COLOUR_RGB_WHITE + "LED", 'W_LED'], + [Blockly.Msg.COLOUR_RGB_RED + "LED", 'R_LED'], + [Blockly.Msg.COLOUR_RGB_YELLOW + "LED", 'Y_LED'], + [Blockly.Msg.COLOUR_RGB_GREEN + "LED", 'G_LED'], + [Blockly.Msg.COLOUR_RGB_BLUE + "LED", 'B_LED'], + [Blockly.Msg.MIXLY_SERVO_MOTOR, 'ext_servo'] + ]), "name") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_EXTERN_GET_ADDR) + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const mixbot_actuator_extern_set_addr = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXBOT) + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MOTOR, 'ext_motor'], + [Blockly.Msg.MIXLY_TRAFFIC_LIGHT, 'ext_traffic'], + [Blockly.Msg.COLOUR_RGB_WHITE + "LED", 'W_LED'], + [Blockly.Msg.COLOUR_RGB_RED + "LED", 'R_LED'], + [Blockly.Msg.COLOUR_RGB_YELLOW + "LED", 'Y_LED'], + [Blockly.Msg.COLOUR_RGB_GREEN + "LED", 'G_LED'], + [Blockly.Msg.COLOUR_RGB_BLUE + "LED", 'B_LED'], + [Blockly.Msg.MIXLY_SERVO_MOTOR, 'ext_servo'] + ]), "name") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_EXTERN_SET_ADDR) + this.appendValueInput('old') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE); + this.appendValueInput('new') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_UPDATE); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +//educore +export const PIN_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_AT) + .appendField(Blockly.Msg.MIXLY_PIN); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const pin_led_bright = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('pin') + .appendField('LED') + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const servo_PIN_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SERVO + Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_AT) + .appendField(Blockly.Msg.MIXLY_PIN); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const servo_move_angle = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_SERVO); + this.appendValueInput("angle") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DISPLAY_MATRIX_ROTATE); + this.appendDummyInput() + .appendField(Blockly.Msg.DRAW_POINTER_ANGLE) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const parrot_PIN_init = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MOTOR + Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_AT) + .appendField(Blockly.Msg.MIXLY_PIN); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const parrot_move_speed = { + init: function () { + this.setColour(ACTUATOR_EXTERN_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_MOTOR); + this.appendValueInput("speed") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DISPLAY_MATRIX_ROTATE + Blockly.Msg.MIXLY_SPEED); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/actuator_onboard.js b/mixly/boards/default_src/micropython/blocks/actuator_onboard.js new file mode 100644 index 00000000..5e86db27 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/actuator_onboard.js @@ -0,0 +1,1911 @@ +import * as Blockly from 'blockly/core'; +import { Boards } from 'mixly'; + +const ACTUATOR_ONBOARD_HUE = '#6C9858' + +//LED +export const number = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["L1", "1"], + ["L2", "2"] + ]), 'op') + this.setOutput(true); + } +}; + +export const ledswitch = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_ON, "1"], + [Blockly.Msg.MIXLY_ESP32_OFF, "0"], + [Blockly.Msg.MIXLY_ESP32_TOGGLE, "-1"] + ]), "flag"); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const actuator_led_bright = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_SETONOFF); + } +}; + +export const actuator_get_led_bright = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETBRIGHT); + } +}; + +export const actuator_get_led_state = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + +export const actuator_led_brightness = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_BUILDIN_LED + Blockly.Msg.MIXLY_BRIGHTNESS + '(0-100%)'); + } +}; + +export const actuator_mixgo_zero_led_color = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('led') + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LCD_SETCOLOR) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LIGHT_RED, "1"], + [Blockly.Msg.MIXLY_LIGHT_GREEN, "2"], + [Blockly.Msg.MIXLY_LIGHT_BLUE, "3"], + [Blockly.Msg.MIXLY_LIGHT_YELLOW, "4"], + [Blockly.Msg.MIXLY_LIGHT_CYAN, "5"], + [Blockly.Msg.MIXLY_LIGHT_PURPLE, "6"], + [Blockly.Msg.MIXLY_LIGHT_WHITE, "7"] + ]), 'colorvalue'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(); + } +}; + +export const rm_actuator_led_bright = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING) + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_RED, "r"], + [Blockly.Msg.COLOUR_RGB_GREEN, "g"] + ]), "color"); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_SETONOFF); + } +}; + +export const rm_actuator_get_led_bright = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_RED, "r"], + [Blockly.Msg.COLOUR_RGB_GREEN, "g"] + ]), "color"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + +export const rm_actuator_get_led_state = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_RED, "r"], + [Blockly.Msg.COLOUR_RGB_GREEN, "g"] + ]), "color"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + +export const rm_actuator_led_brightness = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING) + .appendField(Blockly.Msg.MIXLY_BUILDIN_LED) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_RED, "r"], + [Blockly.Msg.COLOUR_RGB_GREEN, "g"] + ]), "color"); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_BUILDIN_LED + Blockly.Msg.MIXLY_BRIGHTNESS + '(0-10)'); + } +}; + +export const cc_number = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["L1", "20"], + ["L2", "21"] + ]), 'op') + this.setOutput(true); + } +}; + +export const actuator_onboard_neopixel_rgb = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + const boardKey = Boards.getSelectedBoardKey(); + switch (boardKey) { + case 'micropython:esp32c3:mixgo_cc': + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOCC); + break; + case 'micropython:esp32s2:mixgo_ce': + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOCC); + break; + case 'micropython:esp32c3:mixgo_me': + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOME); + break; + case 'micropython:esp32:mPython': + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MPYTHON); + break; + default: + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOME); + } + } +}; + +export const actuator_onboard_neopixel_rgb_all = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_ALL_R_G_B_MIXGOCC); + } +}; + +export const actuator_onboard_neopixel_rgb_show_all_rainbow = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RAINBOW); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_DURATION) + .appendField(Blockly.Msg.MIXLY_MILLIS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + } +}; + + +export const actuator_onboard_neopixel_rgb_show_all_chase = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_CHASE); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.PYTHON_RANGE_STEP) + .appendField(Blockly.Msg.MIXLY_MILLIS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + } +}; + +export const actuator_onboard_neopixel_write = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_RGB_WRITE) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_WRI); + } +}; + + +export const actuator_rm_onboard_neopixel_rgb = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + const boardKey = Boards.getSelectedBoardKey(); + switch (boardKey) { + case 'micropython:esp32c3:mixgocc': + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOCC); + break; + case 'micropython:esp32c3:mixgome': + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOME); + break; + case 'micropython:esp32:mPython': + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MPYTHON); + break; + default: + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOME); + } + } +}; + +export const actuator_rm_onboard_neopixel_rgb_all = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_ALL_R_G_B_MIXGOCC); + } +}; + + + +export const actuator_rm_onboard_neopixel_rgb_show_all_chase = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_CHASE); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.PYTHON_RANGE_STEP) + .appendField(Blockly.Msg.MIXLY_MILLIS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + } +}; + + +export const esp32_music_set_tempo = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('TICKS') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_SET_TEMPO) + .appendField(Blockly.Msg.MICROBIT_ACTUATOR_ticks); + this.appendValueInput('BPM') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_SET_TEMPO); + } +} + +export const esp32_music_get_tempo = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Get_current_tempo) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_GET_TEMPO); + } +} + +export const esp32_music_reset = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_music) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_RESET); + } +} + +export const esp32_onboard_music_pitch = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TONE); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE); + } +}; + +export const esp32_onboard_music_pitch_with_time = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TONE); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_DURATION); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE2); + } +}; + +export const esp32_onboard_music_stop = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_NOTONE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const esp32_onboard_music_play_list = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS); + + } +} + +export const backstage_onboard_music_play_list = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_BACKSTAGE + Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_PLAY_LISTS); + + } +} + +export const rm_motor = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MOTOR_DC) + .appendField(new Blockly.FieldDropdown([ + ['1', "1"], + ["2", "2"], + ["3", "3"] + ]), "wheel"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, "CW"], + [Blockly.Msg.ANTI_CLOCKWISE, "CCW"], + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +//c3 motor onboard + +export const actuator_stepper_keep = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField("MixGo Car") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.blockpy_forward, "F"], + [Blockly.Msg.blockpy_backward, "B"], + [Blockly.Msg.blockpy_left, "L"], + [Blockly.Msg.blockpy_right, "R"] + ]), "VAR"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.appendDummyInput() + .appendField('%') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const actuator_stepper_stop = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MixGo Car") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "VAR"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + } +}; + +export const actuator_dc_motor = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MOTOR_DC) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLYCAR_WHEEL_LEFT, "L"], + [Blockly.Msg.MIXLYCAR_WHEEL_RIGHT, "R"] + ]), "wheel"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, "CW"], + [Blockly.Msg.ANTI_CLOCKWISE, "CCW"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.appendDummyInput() + .appendField('%') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const actuator_dc_motor_stop = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MOTOR_DC) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLYCAR_WHEEL_LEFT, "L"], + [Blockly.Msg.MIXLYCAR_WHEEL_RIGHT, "R"] + ]), "wheel"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_STOP) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "direction"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +//mixbot onboard_motor below: + +export const mixbot_motor_status = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_MOTOR_STATUS); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_MOTOR_STATUS_TOOLTIP); + } +}; + +export const mixbot_move = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXBOT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.blockpy_forward, "F"], + [Blockly.Msg.blockpy_backward, "B"], + [Blockly.Msg.blockpy_left, "L"], + [Blockly.Msg.blockpy_right, "R"] + ]), "VAR"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER, "PWR"], + [Blockly.Msg.MIXLY_SPEED, "SPEED"], + [Blockly.Msg.MIXLY_MIXBOT_MOTOR_TURNS, "TURNS"] + ]), "mode"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_MOVE_TOOLTIP); + } +} + +export const mixbot_stop = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXBOT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "VAR"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const mixbot_motor = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXBOT) + .appendField(Blockly.Msg.MIXLY_MOTOR) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "1"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "2"], + [Blockly.Msg.TEXT_TRIM_BOTH, "0"] + ]), "wheel"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER, "PWR"], + [Blockly.Msg.MIXLY_SPEED, "SPEED"], + [Blockly.Msg.MIXLY_MIXBOT_MOTOR_TURNS, "TURNS"] + ]), "mode"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_MOVE_TOOLTIP); + } +} + +export const actuator_mixbot_buzzer_on_off = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_BUZZER); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_ON, "0"], + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_OFF, "1"] + ]), 'on_off') + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +//bitbot onboard_motor below: +export const bitbot_move = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.BITBOT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.blockpy_forward, "F"], + [Blockly.Msg.blockpy_backward, "B"], + [Blockly.Msg.blockpy_left, "L"], + [Blockly.Msg.blockpy_right, "R"] + ]), "VAR"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const bitbot_stop = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.BITBOT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "VAR"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const bitbot_motor = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.BITBOT) + .appendField(Blockly.Msg.MIXLY_MOTOR) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "0"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "1"] + ]), "wheel"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, "CW"], + [Blockly.Msg.ANTI_CLOCKWISE, "CCW"], + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const actuator_mixgo_nova_mic_set = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_MIXBOT_SOUND_SET_LOUDNESS) + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_SETONOFF); + } +}; + +export const actuator_mixgo_nova_mic_get = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_SOUND_LOUDNESS + '(%)'); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + +export const actuator_mixgo_nova_voice_set = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_MIXBOT_BUZZER + Blockly.Msg.MIXLY_MP3_VOL) + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_SETONOFF); + } +}; + +export const actuator_mixgo_nova_voice_get = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_MIXBOT_BUZZER + Blockly.Msg.MIXLY_MP3_VOL + '(%)'); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + + + +export const actuator_mixgo_nova_record_audio = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('PATH') + .appendField(Blockly.Msg.MIXLY_RECORD_AUDIO) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH); + this.appendValueInput('TIME') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_GET_PRESSES_TIME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const actuator_mixgo_nova_play_audio = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('PATH') + .appendField(Blockly.Msg.MIXLY_PLAY_AUDIO) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const actuator_mixgo_nova_play_online_audio = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('PATH') + .appendField(Blockly.Msg.MIXLY_PLAY_ONLINE_AUDIO) + .appendField('URL'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const actuator_mixgo_nova_onboard_music_pitch = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TONE); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_TONE); + } +}; + +export const actuator_mixgo_nova_onboard_music_stop = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_NOTONE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const set_power_output = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(Blockly.Msg.PIN_NUMBERING); + const boardKey = Boards.getSelectedBoardKey(); + switch (boardKey) { + case 'micropython:esp32c2:mixgo_mini': + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([["1", "1"], ["2", "2"]]), "index"); + break; + case 'micropython:esp32c5:mixgo_sowl': + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([["1", "1"], ["2", "2"], ["4", "4"], ["5", "5"]]), "index"); + break; + default: + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([["1", "1"], ["2", "2"], ["3", "3"], ["4", "4"]]), "index"); + } + this.appendValueInput('duty') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.blynk_IOT_IR_POWER + Blockly.Msg.MIXLY_PINMODEOUT); + this.appendDummyInput() + .appendField('%') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(); + } +} + +export const get_power_output = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(Blockly.Msg.PIN_NUMBERING); + const boardKey = Boards.getSelectedBoardKey(); + switch (boardKey) { + case 'micropython:esp32c2:mixgo_mini': + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([["1", "1"], ["2", "2"]]), "index"); + break; + case 'micropython:esp32c5:mixgo_sowl': + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([["1", "1"], ["2", "2"], ["4", "4"], ["5", "5"]]), "index"); + break; + default: + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([["1", "1"], ["2", "2"], ["3", "3"], ["4", "4"]]), "index"); + } + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.blynk_IOT_IR_POWER + Blockly.Msg.MIXLY_PINMODEOUT + Blockly.Msg.MIXLY_DUTY_RATIO); + this.setOutput(true, Number); + this.setInputsInline(true); + } +} + +export const set_all_power_output = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(Blockly.Msg.MIXLY_ALL + Blockly.Msg.PIN_NUMBERING); + this.appendValueInput('duty') + .setCheck(Number) + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.blynk_IOT_IR_POWER + Blockly.Msg.MIXLY_PINMODEOUT + Blockly.Msg.MIXLY_FREQUENCY); + this.appendDummyInput() + .appendField('Hz') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_MOTOR_EXTERN_TOOLTIP); + } +} + +export const set_part_power_output = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(new Blockly.FieldDropdown([["1-2", "1"], ["4-5", "4"]]), "index"); + this.appendValueInput('duty') + .setCheck(Number) + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.blynk_IOT_IR_POWER + Blockly.Msg.MIXLY_PINMODEOUT + Blockly.Msg.MIXLY_FREQUENCY); + this.appendDummyInput() + .appendField('Hz') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_MOTOR_EXTERN_TOOLTIP); + } +} + +export const analog_keyboard_input = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD_INPUT); + this.appendValueInput('special'); + this.appendValueInput('general'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RELEASE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'release'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD_INPUT); + } +}; + +export const special_key = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SPECIAL_KEY) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SPECIAL_KEY0, "0x00"], + [Blockly.Msg.MIXLY_SPECIAL_KEY1, "0x01"], + [Blockly.Msg.MIXLY_SPECIAL_KEY2, "0x02"], + [Blockly.Msg.MIXLY_SPECIAL_KEY4, "0x04"], + [Blockly.Msg.MIXLY_SPECIAL_KEY8, "0x08"], + [Blockly.Msg.MIXLY_SPECIAL_KEY16, "0x10"], + [Blockly.Msg.MIXLY_SPECIAL_KEY32, "0x20"], + [Blockly.Msg.MIXLY_SPECIAL_KEY64, "0x40"], + [Blockly.Msg.MIXLY_SPECIAL_KEY128, "0x80"] + ]), 'op') + this.setOutput(true); + } +}; + +export const general_key = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GENERAL_KEY) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SPECIAL_KEY0, "0x00"], + ['A', "0x04"], + ['B', "0x05"], + ['C', "0x06"], + ['D', "0x07"], + ['E', "0x08"], + ['F', "0x09"], + ['G', "0x0A"], + ['H', "0x0B"], + ['I', "0x0C"], + ['J', "0x0D"], + ['K', "0x0E"], + ['L', "0x0F"], + ['M', "0x10"], + ['N', "0x11"], + ['O', "0x12"], + ['P', "0x13"], + ['Q', "0x14"], + ['R', "0x15"], + ['S', "0x16"], + ['T', "0x17"], + ['U', "0x18"], + ['V', "0x19"], + ['W', "0x1A"], + ['X', "0x1B"], + ['Y', "0x1C"], + ['Z', "0x1D"], + ['1 !', "0x1E"], + ['2 @', "0x1F"], + ['3 #', "0x20"], + ['4 $', "0x21"], + ['5 %', "0x22"], + ['6 ^', "0x23"], + ['7 &', "0x24"], + ['8 *', "0x25"], + ['9 (', "0x26"], + ['0 )', "0x27"], + ['ENTER', "0x28"], + ['ESC', "0x29"], + ['BACKSPACE', "0x2A"], + ['TAB', "0x2B"], + ['SPACE', "0x2C"], + ['- _', "0x2D"], + ['= +', "0x2E"], + ['[ {', "0x2F"], + ['] }', "0x30"], + ['\\ |', "0x31"], + ['; :', "0x33"], + ["' " + ' "', "0x34"], + ['` ~', "0x35"], + [', <', "0x36"], + ['. >', "0x37"], + ['/ ?', "0x38"], + ['CAPS_LOCK', "0x39"], + ['F1', "0x3A"], + ['F2', "0x3B"], + ['F3', "0x3C"], + ['F4', "0x3D"], + ['F5', "0x3E"], + ['F6', "0x3F"], + ['F7', "0x40"], + ['F8', "0x41"], + ['F9', "0x42"], + ['F10', "0x43"], + ['F11', "0x44"], + ['F12', "0x45"], + ['PRINTSCREEN', "0x46"], + ['SCROLL_LOCK', "0x47"], + ['PAUSE', "0x48"], + ['INSERT', "0x49"], + ['HOME', "0x4A"], + ['PAGE_UP', "0x4B"], + ['DELETE', "0x4C"], + ['END', "0x4D"], + ['PAGE_DOWN', "0x4E"], + ['RIGHT', "0x4F"], + ['LEFT', "0x50"], + ['DOWN', "0x51"], + ['UP', "0x52"], + ['NUM_LOCK', "0x53"], + ['/', "0x54"], + ['*', "0x55"], + ['-', "0x56"], + ['+', "0x57"], + ['ENTER', "0x58"], + ['1', "0x59"], + ['2', "0x5A"], + ['3', "0x5B"], + ['4', "0x5C"], + ['5', "0x5D"], + ['6', "0x5E"], + ['7', "0x5F"], + ['8', "0x60"], + ['9', "0x61"], + ['0', "0x62"], + ['.', "0x63"] + ]), 'op') + this.setOutput(true); + } +}; + + +export const general_key_tuple = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.itemCount_ = 2; + this.updateShape_(); + this.setOutput(true); + this.setMutator(new Blockly.icons.MutatorIcon(['generalkey_create_with_item'], this)); + this.setTooltip(Blockly.Msg.GENERALKEY_TUPLE_CREATE_TOOLTIP); + }, + + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('generalkey_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('generalkey_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.GENERALKEY_CREATE_EMPTY_TITLE); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.GENERALKEY_CREATE_WITH_INPUT_WITH); + } + } + } + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const generalkey_container = { + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GENERAL_KEY); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.GENERALKEY_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const generalkey_create_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_SET_VARIABLES_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.TUPLE_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const analog_mouse_input = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_MOUSE_INPUT); + this.appendValueInput('key'); + this.appendValueInput('x') + .appendField(Blockly.Msg.MIXLY_X_CHANGES); + this.appendValueInput('y') + .appendField(Blockly.Msg.MIXLY_Y_CHANGES); + this.appendValueInput('wheel') + .appendField(Blockly.Msg.MIXLY_WHEEL_CHANGES); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RELEASE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'release'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD_INPUT); + } +}; + +export const mouse_key = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MOUSE_KEYS) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SPECIAL_KEY0, "0x00"], + [Blockly.Msg.MIXLY_MOUSE_LEFT_KEY, "0x01"], + [Blockly.Msg.MIXLY_MOUSE_RIGHT_KEY, "0x02"], + [Blockly.Msg.MIXLY_MOUSE_MID_KEY, "0x04"] + ]), 'op') + this.setOutput(true); + } +}; + +export const analog_keyboard_str = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD_INPUT); + this.appendValueInput('str') + .appendField(Blockly.Msg.MIXLY_STR_PRINT); + this.appendValueInput('time') + .appendField(Blockly.Msg.MIXLY_STR_PRINT_TIME_DELAY); + this.appendDummyInput() + .appendField('ms'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const analog_ble_keyboard_init = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD); + this.appendValueInput('kname') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_SYSTEM_DEVICE_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const ble_keyboard_get_mac = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD + Blockly.Msg.MIXLY_BELONG + Blockly.Msg.MIXLY_ETHERNET_MAC_ADDRESS); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const ble_keyboard_connect = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD + Blockly.Msg.MIXLY_IS_CONNECT); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const analog_ble_keyboard_input = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD) + .appendField(Blockly.Msg.MIXLY_SEND_KEYBOARD); + this.appendValueInput('special'); + this.appendValueInput('general'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RELEASE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'release'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD_INPUT); + } +}; + +export const analog_ble_keyboard_str = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD); + this.appendValueInput('str') + .appendField(Blockly.Msg.MIXLY_SEND_KEYBOARD + Blockly.Msg.MIXLY_STR_PRINT); + this.appendValueInput('time') + .appendField(Blockly.Msg.MIXLY_STR_PRINT_TIME_DELAY); + this.appendDummyInput() + .appendField('ms'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const analog_ble_keyboard_send_battery = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD); + this.appendValueInput('battery') + .appendField(Blockly.Msg.MIXLY_SEND_KEYBOARD + Blockly.Msg.MIXLY_BELONG + Blockly.Msg.MIXLY_BATTERY + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO); + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const analog_ble_mouse_init = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_MOUSE); + this.appendValueInput('name') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_SYSTEM_DEVICE_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const ble_mouse_get_mac = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_MOUSE + Blockly.Msg.MIXLY_BELONG + Blockly.Msg.MIXLY_ETHERNET_MAC_ADDRESS); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const ble_mouse_connect = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_MOUSE + Blockly.Msg.MIXLY_IS_CONNECT); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const analog_ble_mouse_input = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_MOUSE) + .appendField(Blockly.Msg.MIXLY_SEND + Blockly.Msg.MIXLY_MOUSE_INPUT); + this.appendValueInput('key'); + this.appendValueInput('x') + .appendField(Blockly.Msg.MIXLY_X_CHANGES); + this.appendValueInput('y') + .appendField(Blockly.Msg.MIXLY_Y_CHANGES); + this.appendValueInput('wheel') + .appendField(Blockly.Msg.MIXLY_WHEEL_CHANGES); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RELEASE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'release'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD_INPUT); + } +}; + +export const analog_ble_mouse_send_battery = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_MOUSE); + this.appendValueInput('battery') + .appendField(Blockly.Msg.MIXLY_SEND + Blockly.Msg.MIXLY_MOUSE + Blockly.Msg.MIXLY_BELONG + Blockly.Msg.MIXLY_BATTERY + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO); + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const analog_ble_keyboard_mouse_init = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_KEYBOARD_AND_MOUSE); + this.appendValueInput('kname') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_SYSTEM_DEVICE_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const ble_keyboard_mouse_get_mac = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_KEYBOARD_AND_MOUSE + Blockly.Msg.MIXLY_BELONG + Blockly.Msg.MIXLY_ETHERNET_MAC_ADDRESS); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const ble_keyboard_mouse_connect = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_KEYBOARD_AND_MOUSE + Blockly.Msg.MIXLY_IS_CONNECT); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const analog_ble_keyboard_mouse_send_battery = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_KEYBOARD_AND_MOUSE); + this.appendValueInput('battery') + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_BATTERY + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO); + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const analog_ble_keyboard_mouse_input = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_KEYBOARD_AND_MOUSE) + .appendField(Blockly.Msg.MIXLY_SEND_KEYBOARD); + this.appendValueInput('special'); + this.appendValueInput('general'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RELEASE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'release'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD_INPUT); + } +}; + +export const analog_ble_keyboard_mouse_str = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_KEYBOARD_AND_MOUSE); + this.appendValueInput('str') + .appendField(Blockly.Msg.MIXLY_SEND_KEYBOARD + Blockly.Msg.MIXLY_STR_PRINT); + this.appendValueInput('time') + .appendField(Blockly.Msg.MIXLY_STR_PRINT_TIME_DELAY); + this.appendDummyInput() + .appendField('ms'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const analog_ble_mouse_keyboard_input = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_KEYBOARD_AND_MOUSE) + .appendField(Blockly.Msg.MIXLY_SEND + Blockly.Msg.MIXLY_MOUSE_INPUT); + this.appendValueInput('key'); + this.appendValueInput('x') + .appendField(Blockly.Msg.MIXLY_X_CHANGES); + this.appendValueInput('y') + .appendField(Blockly.Msg.MIXLY_Y_CHANGES); + this.appendValueInput('wheel') + .appendField(Blockly.Msg.MIXLY_WHEEL_CHANGES); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RELEASE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'release'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_MOUSE_INPUT); + } +}; +//educore actuator +export const educore_buzzer = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIDI); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const educore_buzzer_play_tone = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("buzzer"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TONE); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const educore_buzzer_play_tone_time = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("buzzer"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TONE); + this.appendValueInput('pitch') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY); + this.appendValueInput('time') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_DURATION); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const educore_buzzer_stop = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("buzzer") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Turn_off_display); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const educore_rgb_light = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RGB); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const educore_neopixel_rgb = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("rgb"); + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendValueInput("RVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_R); + this.appendValueInput("GVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_G); + this.appendValueInput("BVALUE") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_B); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + // const boardKey = Boards.getSelectedBoardKey(); + // switch (boardKey) { + // case 'micropython:esp32c3:mixgo_cc': + // this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOCC); + // break; + // case 'micropython:esp32s2:mixgo_ce': + // this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOCC); + // break; + // case 'micropython:esp32c3:mixgo_me': + // this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOME); + // break; + // case 'micropython:esp32:mPython': + // this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MPYTHON); + // break; + // default: + // this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B_MIXGOME); + // } + } +}; + +export const educore_neopixel_clear = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("rgb"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Turn_off_display) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const educore_ble_sensor_init = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("name") + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_MICROBIT_JS_SYSTEM_DEVICE_NAME + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_AS); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_ble_sensor_connected = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_BLUETOOTH); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_BE_CONNETCED) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_ble_keyboard_input = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_KEYBOARD); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SEND_KEYBOARD); + this.appendValueInput('general'); + // this.appendDummyInput() + // .appendField(Blockly.Msg.MIXLY_RELEASE) + // .appendField(new Blockly.FieldDropdown([ + // [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + // [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + // ]), 'release'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const get_keyboard_light = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_KEYBOARD_LIGHT) + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_NumLock, "0"], + [Blockly.Msg.MIXLY_CapsLock, "1"], + [Blockly.Msg.MIXLY_ScorllLock, "2"] + ]), 'key'); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const set_microphone_amplification = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_MICROPHONE_AMPLIFICATION) + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + ['4x', "0"], + ['8x', "1"], + ['16x', "2"], + ['32x', "3"] + ]), 'times'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const record_audio = { + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('str') + .appendField(Blockly.Msg.MIXPY_AI_AUDIO); + this.appendValueInput('time') + .appendField(Blockly.Msg.MIXPY_AI_AUDIO_TIME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const set_music_volume ={ + init: function () { + this.setColour(ACTUATOR_ONBOARD_HUE); + this.appendValueInput('percent') + .appendField(Blockly.Msg.MIXLY_MUSIC_VOLUME_SET); + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/ai.js b/mixly/boards/default_src/micropython/blocks/ai.js new file mode 100644 index 00000000..0d378e72 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/ai.js @@ -0,0 +1,68 @@ +import * as Blockly from 'blockly/core'; + +const AI_HUE = 205; + +export const MICROPYTHON_AI_client = { + init: function () { + this.setColour(AI_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_AipSpeech_asr, "ASR"], + [Blockly.Msg.MIXLY_AI_UNIT, "UNIT"] + ]), 'CTYPE') + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_Client) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('API_KEY') + .appendField('API_KEY') + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('SECRET_KEY') + .appendField('SECRET_KEY') + .setAlign(Blockly.inputs.Align.RIGHT); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const MICROPYTHON_AI_Speech_unit = { // AI_TYPE_FUNC + init: function () { + this.setColour(AI_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_AI_UNIT) + .appendField(Blockly.Msg.MIXLY_Client) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('ID') + .appendField('ID') + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('STR') + .appendField(Blockly.Msg.OLED_STRING) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const MICROPYTHON_AI_Speech_asr = { // AI_TYPE_FUNC + init: function () { + this.setColour(AI_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr) + .appendField(Blockly.Msg.MIXLY_Client) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('FILE') + .appendField(Blockly.Msg.MIXPY_AI_AUDIO_TIME) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LANGUAGE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_AI_LANGUAGE_CHINESE, "1537"], + [Blockly.Msg.MIXLY_AI_LANGUAGE_ENGLISH, "1737"], + [Blockly.Msg.MIXLY_AI_LANGUAGE_CANTONESE, "1637"] + ]), 'LANGUAGE') + this.setInputsInline(true); + this.setOutput(true); + } +}; + diff --git a/mixly/boards/default_src/micropython/blocks/ai_cloud.js b/mixly/boards/default_src/micropython/blocks/ai_cloud.js new file mode 100644 index 00000000..fc1443ba --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/ai_cloud.js @@ -0,0 +1,252 @@ +import * as Blockly from 'blockly/core'; +import { Variables } from '../../python/export'; +const AI_CLOUD_VOICE_HUE = '#88ada6'; + +export const init_xunfei_vi = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_AS + Blockly.Msg.MIXLY_XUFEI + Blockly.Msg.MIXLY_AipSpeech_asr ); + this.appendValueInput('APPID') + .setCheck(String) + .appendField('APPID'); + this.appendValueInput('APISecret') + .setCheck(String) + .appendField('APISecret'); + this.appendValueInput('APIKey') + .setCheck(String) + .appendField('APIKey'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const init_xunfei_Spark_Ultra = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_AS + Blockly.Msg.MIXLY_XUFEI +Blockly.Msg.MIXLY_LARGE_LANGUAGE_MODEL ); + this.appendValueInput('APPID') + .setCheck(String) + .appendField('APPID'); + this.appendValueInput('APISecret') + .setCheck(String) + .appendField('APISecret'); + this.appendValueInput('APIKey') + .setCheck(String) + .appendField('APIKey'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SELECT_MODEL) + .appendField(new Blockly.FieldDropdown([ + ["Spark-X1-32K","Spark X1-32K"], + ["Spark-Lite","Spark Lite"], + ["Spark-Pro","Spark Pro"], + ["Spark-Pro-128K","Spark Pro-128K"], + ["Spark-Max, " + Blockly.Msg.MIXLY_SUPPORT + Blockly.Msg.MIXLY_DIALOGUE_BACKGROUND + "、" + Blockly.Msg.MIXLY_ESP32_ONENET_SUB, "Spark Max"], + ["Spark-Max-32K, "+ Blockly.Msg.MIXLY_SUPPORT + Blockly.Msg.MIXLY_DIALOGUE_BACKGROUND + "、" + Blockly.Msg.MIXLY_ESP32_ONENET_SUB, "Spark Max-32K"], + ["Spark-Ultra-32K, "+ Blockly.Msg.MIXLY_SUPPORT + Blockly.Msg.MIXLY_DIALOGUE_BACKGROUND + "、" + Blockly.Msg.MIXLY_ESP32_ONENET_SUB, "Spark Ultra-32K"], + [Blockly.Msg.MIXLY_KJWX, "Spark kjwx"], + [Blockly.Msg.MIXLY_CUSTOMIZE_MODEL + "," + Blockly.Msg.MIXLY_SUPPORT + Blockly.Msg.MIXLY_ESP32_ONENET_SUB, "Spark Customize"] + ]),"model"); + this.appendValueInput('DBG') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_DIALOGUE_BACKGROUND); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const init_xunfei_Chinese_Model = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_AS + Blockly.Msg.MIXLY_XUFEI+Blockly.Msg.MIXLY_CHINESE_RECOGNIZION+Blockly.Msg.MIXLY_LARGE_LANGUAGE_MODEL ); + this.appendValueInput('APPID') + .setCheck(String) + .appendField('APPID'); + this.appendValueInput('APISecret') + .setCheck(String) + .appendField('APISecret'); + this.appendValueInput('APIKey') + .setCheck(String) + .appendField('APIKey'); + this.appendValueInput('HW') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_HOT_WORD + 'ID'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const xunfei_vi_run = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendValueInput('VAR') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RUN + Blockly.Msg.MIXLY_AipSpeech_asr); + this.appendValueInput('time') + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_AI_AUDIO_TIME); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.init_xunfei_vi_op_tooltip); + } +}; + +export const xunfei_Spark_Ultra_run = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendValueInput('VAR') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RUN + Blockly.Msg.MIXLY_LARGE_LANGUAGE_MODEL); + this.appendValueInput('qus') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_SEND); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.init_xunfei_vi_run_tooltip); + } +}; + +export const init_xunfei_Spark_Ultra_clr_his = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendValueInput('VAR') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RUN + Blockly.Msg.MIXLY_LARGE_LANGUAGE_MODEL + Blockly.Msg.MIXLY_EMPTY_HISTORY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const llm_set_callback = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendValueInput('VAR1') + this.appendValueInput('callback') + .appendField(Blockly.Msg.MIXLY_PYTHON_CONTROLS_THREAD_USE) + this.appendValueInput('VAR2') + .appendField(Blockly.Msg.MIXLY_FUNCTION_NAME); + this.appendValueInput('VAR3') + .appendField(Blockly.Msg.MIXLY_FUNCTION_DESCRIPTION) + + this.itemCount_ = 2; + this.updateShape_(); + + this.setMutator(new Blockly.icons.MutatorIcon(['llm_set_callback_item'], this)); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.llm_set_callback_tooltip); + }, + + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('llm_set_callback_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('llm_set_callback_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i) + .connection.connect(connections[i]); + } + } + }, + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } + if (this.getInput('PARAMS_LABEL')) { + this.removeInput('PARAMS_LABEL'); + } + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + // Rebuild block. + if (this.itemCount_ == 0) { + } else { + this.appendDummyInput('PARAMS_LABEL') + .appendField(Blockly.Msg.MIXLY_PARAMS + Blockly.Msg.OLED_STRING); + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + } + } + } +}; + +export const llm_set_callback_container = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_PARAMS); + this.appendStatementInput('STACK'); + this.contextMenu = false; + } +}; + +export const llm_set_callback_item = { + init: function () { + this.setColour(AI_CLOUD_VOICE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.contextMenu = false; + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/ai_local.js b/mixly/boards/default_src/micropython/blocks/ai_local.js new file mode 100644 index 00000000..820b7750 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/ai_local.js @@ -0,0 +1,1364 @@ +import * as Blockly from 'blockly/core'; +const AI_LOCAL_VOICE_HUE = '#2FAD7A'; +const AI_LOCAL_GRAPH_HUE = '#90A244'; +const IOT_HUE = '#526FC3'; +const DISPLAY_ONBOARD_HUE = '#569A98'; + +export const yesorno = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_FALSE, "False"], + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_TRUE, "1"] + ]), "state"); + this.setOutput(true); + } +}; + +//voice part +export const VOICE_RECOGNITION_CONTROL = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ON,"1"], + [Blockly.Msg.MIXLY_OFF,"0"] + ]),"control") + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} +export const CI130X_OPEN_AND_CLOSE = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ON,"1"], + [Blockly.Msg.MIXLY_OFF,"0"] + ]),"status") + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} +export const CI130X_PLAY_SYSTEM_CMD_SANT = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_AipSpeech_synthesis); + this.appendValueInput('text') + .appendField(Blockly.Msg.MIXLY_TEXT); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SPEED) + .appendField(new Blockly.FieldDropdown([ + ['0', '0'], + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'] + ]), 'speed'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_AipSpeech_synthesis_SANT_TOOLTIP); + } +}; +export const CI130X_IDENTIFY_AND_SAVE_SANT = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + Blockly.Msg.MIXLY_IDENTIFY_ONCE_AND_SAVE) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const CI130X_GET_WHETHER_IDENTIFY_SANT = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_HELLO_XIAOZHI, "1"], + [Blockly.Msg.MIXLY_XIAOZHIXIAOZHI, "2"], + [Blockly.Msg.MIXLY_THE_FIRST, "3"], + [Blockly.Msg.MIXLY_THE_SECOND, "4"], + [Blockly.Msg.MIXLY_THE_THIRD, "5"], + [Blockly.Msg.MIXLY_THE_FOURTH, "6"], + [Blockly.Msg.MIXLY_THE_FIFTH, "7"], + [Blockly.Msg.MIXLY_THE_SIXTH, "8"], + [Blockly.Msg.MIXLY_THE_SEVENTH, "9"], + [Blockly.Msg.MIXLY_THE_EIGHTH, "10"], + [Blockly.Msg.MIXLY_THE_NINTH, "11"], + [Blockly.Msg.MIXLY_THE_TENTH, "12"], + [Blockly.Msg.MIXLY_THE_ELEVENTH, "13"], + [Blockly.Msg.MIXLY_THE_TWELFTH, "14"], + [Blockly.Msg.MIXLY_THE_13TH, "15"], + [Blockly.Msg.MIXLY_THE_14TH, "16"], + [Blockly.Msg.MIXLY_THE_15TH, "17"], + [Blockly.Msg.MIXLY_THE_16TH, "18"], + [Blockly.Msg.MIXLY_THE_17TH, "19"], + [Blockly.Msg.MIXLY_THE_18TH, "20"], + [Blockly.Msg.MIXLY_THE_19TH, "21"], + [Blockly.Msg.MIXLY_THE_20TH, "22"], + [Blockly.Msg.MIXLY_Turn_on_the_lights, "23"], + [Blockly.Msg.MIXLY_Turn_off_the_lights, "24"], + [Blockly.Msg.MIXLY_Turn_up_the_brightness, "25"], + [Blockly.Msg.MIXLY_Turn_down_the_brightness, "26"], + [Blockly.Msg.MIXLY_Set_it_to_red, "27"], + [Blockly.Msg.MIXLY_Set_it_to_orange, "28"], + [Blockly.Msg.MIXLY_Set_it_to_yellow, "29"], + [Blockly.Msg.MIXLY_Set_it_to_green, "30"], + [Blockly.Msg.MIXLY_Set_it_to_cyan, "31"], + [Blockly.Msg.MIXLY_Set_it_to_blue, "32"], + [Blockly.Msg.MIXLY_Set_it_to_purple, "33"], + [Blockly.Msg.MIXLY_Set_it_to_white, "34"], + [Blockly.Msg.MIXLY_Turn_on_the_fan, "35"], + [Blockly.Msg.MIXLY_Turn_off_the_fan, "36"], + [Blockly.Msg.MIXLY_First_gear, "37"], + [Blockly.Msg.MIXLY_Wind_speed_second, "38"], + [Blockly.Msg.MIXLY_Third_gear, "39"], + [Blockly.Msg.MIXLY_Previous, "40"], + [Blockly.Msg.MIXLY_Next_page, "41"], + [Blockly.Msg.MIXLY_Show_smiley_face, "42"], + [Blockly.Msg.MIXLY_Show_crying_face, "43"], + [Blockly.Msg.MIXLY_Show_love, "44"], + [Blockly.Msg.MIXLY_Close_display, "45"], + [Blockly.Msg.MIXLY_Start_execution, "46"], + [Blockly.Msg.MIXLY_FORWARD, "47"], + [Blockly.Msg.MIXLY_BACKWARD, "48"], + [Blockly.Msg.MIXLY_TURNLEFT, "49"], + [Blockly.Msg.MIXLY_TURNRIGHT, "50"], + [Blockly.Msg.MIXLY_STOP, "51"], + [Blockly.Msg.MIXLY_Accelerate, "52"], + [Blockly.Msg.MIXLY_retard, "53"], + [Blockly.Msg.ROTATION_FORWARD, "54"], + [Blockly.Msg.ROTATION_BACKWARD, "55"], + [Blockly.Msg.MIXLY_Query_temperature, "56"], + [Blockly.Msg.MIXLY_Query_humidity, "57"], + [Blockly.Msg.MIXLY_Query_brightness, "58"], + [Blockly.Msg.MIXLY_Query_sound, "59"], + [Blockly.Msg.MIXLY_Query_time, "60"], + [Blockly.Msg.MIXLY_Query_distance, "61"], + [Blockly.Msg.MIXLY_Query_pressure, "62"], + [Blockly.Msg.MIXLY_Query_key, "63"], + [Blockly.Msg.MIXLY_Query_touch, "64"], + [Blockly.Msg.MIXLY_Query_color, "65"] + ]), "cmd") + .appendField(Blockly.Msg.MIXLY_WHETHER + Blockly.Msg.MIXLY_BE_IDENTIFIED); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const CI130X_GET_THE_RECOGNIZED_CMD_SANT = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RECOGNIZED_STATE, "status1"], + [Blockly.Msg.MIXLY_WHETHER_BROADCAST, "status2"], + [Blockly.Msg.MIXLY_THE_RECOGNIZED_CMD, "result"], + [Blockly.Msg.MIXLY_ENABLE_STATUS,"status3"] + ]), "key") + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_CI130X_GET_THE_RECOGNIZED_STATE_TOOLTIP); + } +}; + +export const CI130X_BROADCAST_SANT = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + Blockly.Msg.MIXLY_MP3_PLAY) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_INOUT_PULL_NONE, "None"], + [Blockly.Msg.MIXLY_WIND_SPEED, "154"], + [Blockly.Msg.MIXLY_HYETAL, "155"], + [Blockly.Msg.MIXLY_TEMPERATURE, "156"], + [Blockly.Msg.MIXLY_Humidity, "157"], + [Blockly.Msg.MIXLY_Altitude, "158"], + [Blockly.Msg.MIXLY_SOUND, "159"], + [Blockly.Msg.MIXLY_BRIGHTNESS, "160"], + [Blockly.Msg.ME_GO_HALL_SENSOR_DISTANCE, "161"], + [Blockly.Msg.MIXLY_SERVO, "162"], + [Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, "163"], + [Blockly.Msg.MIXLY_BUTTON2, "164"], + [Blockly.Msg.MIXLY_ESP32_TOUCH, "165"], + [Blockly.Msg.MIXLY_PAY, "166"], + [Blockly.Msg.MIXLY_CARSH_CHANGE, "167"], + [Blockly.Msg.MIXLY_COUNTDOWN, "168"], + [Blockly.Msg.MIXLY_TIMING, "169"], + [Blockly.Msg.MIXLY_AT_THE_MOMENT, "170"], + [Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE, "171"], + [Blockly.Msg.MIXLY_FORWARD, "172"], + [Blockly.Msg.MIXLY_BACKWARD, "173"], + [Blockly.Msg.MIXLY_TURNLEFT, "174"], + [Blockly.Msg.MIXLY_TURNRIGHT, "175"], + [Blockly.Msg.MIXLY_STOP, "176"], + [Blockly.Msg.MIXLY_Accelerate, "177"], + [Blockly.Msg.MIXLY_retard, "178"], + [Blockly.Msg.ROTATION_FORWARD, "179"], + [Blockly.Msg.ROTATION_BACKWARD, "180"], + [Blockly.Msg.TUPLE_JOIN, "181"], + [Blockly.Msg.MIXLY_SHOW, "182"], + [Blockly.Msg.MIXLY_LAMPLIGHT, "183"], + [Blockly.Msg.MIXLY_ACCELERATION, "184"] + ]), "star"); + this.appendValueInput('NUM') + .appendField(Blockly.Msg.MIXLY_NUMBER); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_UNIT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_INOUT_PULL_NONE, "None"], + [Blockly.Msg.MIXLY_YEAR, "117"], + [Blockly.Msg.MIXLY_MONTH, "118"], + [Blockly.Msg.MIXLY_DAY, "119"], + [Blockly.Msg.MIXLY_HOUR, "120"], + [Blockly.Msg.MIXLY_MINUTE, "121"], + [Blockly.Msg.MIXLY_SECOND, "122"], + [Blockly.Msg.MIXLY_WEEK2, "123"], + [Blockly.Msg.MIXLY_RMB_UNIT, "124"], + [Blockly.Msg.blockpy_setheading_degree, "125"], + [Blockly.Msg.MIXLY_GEAR, "126"], + [Blockly.Msg.MIXLY_LAYER, "127"], + [Blockly.Msg.MIXLY_GRAM, "128"], + [Blockly.Msg.MIXLY_METER, "129"], + [Blockly.Msg.MIXLY_CENTIMETER, "130"], + [Blockly.Msg.MIXLY_MILLIMETER, "131"], + [Blockly.Msg.MIXLY_LUMEN, "132"], + [Blockly.Msg.MIXLY_DECIBEL, "133"], + [Blockly.Msg.MIXLY_hectopascal, "134"], + [Blockly.Msg.MIXLY_PERCENT, "135"], + [Blockly.Msg.MIXLY_CELSIUS, "136"], + [Blockly.Msg.MIXLY_METER_PER_SEC, "137"], + [Blockly.Msg.MIXLY_MICROBIT_Turn_on_display, "138"], + [Blockly.Msg.MIXLY_MICROBIT_Turn_off_display, "139"], + [Blockly.Msg.MIXLY_SUCCESS, "140"], + [Blockly.Msg.MIXLY_FAILED, "141"], + [Blockly.Msg.MIXLY_WRONG, "142"], + [Blockly.Msg.MIXLY_GOOD, "143"], + [Blockly.Msg.MIXLY_blockpy_set_add, "144"], + [Blockly.Msg.MIXLY_DECREASE, "145"], + [Blockly.Msg.COLOUR_RGB_RED, "146"], + [Blockly.Msg.COLOUR_RGB_ORANGE, "147"], + [Blockly.Msg.COLOUR_YELLOW, "148"], + [Blockly.Msg.COLOUR_RGB_GREEN, "149"], + [Blockly.Msg.COLOUR_CYAN, "150"], + [Blockly.Msg.COLOUR_RGB_BLUE, "151"], + [Blockly.Msg.COLOUR_RGB_PURPLE, "152"], + [Blockly.Msg.COLOUR_RGB_WHITE, "153"] + ]), "end"); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const CI130X_SET_SYSTEM_CMD_SANT = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_SYSTEM + Blockly.Msg.MIXLY_CMD) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MILXY_ENTER_WAKE_UP, "1"], + [Blockly.Msg.MIXLY_INCREASE_VOLUME, "202"], + [Blockly.Msg.MIXLY_REDUCE_VOLUME, "203"], + [Blockly.Msg.MIXLY_MAX_VOLUME, "204"], + [Blockly.Msg.MIXLY_MINIMUM, "205"], + [Blockly.Msg.MIXLY_OPEN_RESPONSE, "206"], + [Blockly.Msg.MIXLY_CLOSE_RESPONSE, "207"], + [Blockly.Msg.MIXLY_QUIT_WAKE_UP, "208"] + ]), "cmd") + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const CI130X_BROADCAST_SYSTEM_TIME = { + init: function () { + this.setColour(AI_LOCAL_VOICE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DETAILED + Blockly.Msg.MIXLY_BROADCAST_SYSTEM_TIME); + this.appendValueInput('boolean'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + + +//graph part +export const CREATE_CAMERA = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_SMARTCAMERA) + .appendField(Blockly.Msg.MIXLY_SHOOTING_SIZE) + .appendField(new Blockly.FieldDropdown([ + ['240px*240px', "R240X240"], + ['320px*320px', "R320X320"], + ['128px*128px', "R128X128"], + ['96px*96px', "R96X96"], + ['VGA : 640px*480px', "VGA"], + ['HVGA : 480px*320px', "HVGA"], + ['QVGA : 320px*240px', "QVGA"], + ['QQVGA : 160px*120px', "QQVGA"] + ]), "cmd"); + this.appendValueInput("HM") + .appendField(Blockly.Msg.MIXLY_HORIZONTAL_MIRRORING) + this.appendValueInput("VF") + .appendField(Blockly.Msg.MIXLY_VERTICAL_MIRRORING); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const SHOOT_AND_SAVE_PICTURE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('direct') + .appendField(Blockly.Msg.MIXLY_SHOOT_AND_SAVE_PICTURE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const GET_IMAGE_AND_SAVE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + this.appendValueInput('direct') + .appendField(Blockly.Msg.MICROPYTHON_HUSKYLENS_SAVE_AS + Blockly.Msg.blockpy_turtle_set_num + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH); + this.appendValueInput('quality') + .appendField(Blockly.Msg.MIXLY_IMAGE_QUALITY); + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_ROTATION_ANGLE) + .appendField(new Blockly.FieldDropdown([ + ['0','0'], + ['90','90'], + ['180','180'], + ['270','270'] + ]),'angle'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const OPEN_IMAGE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('direct') + .appendField(Blockly.Msg.MIXLY_MICROBIT_Turn_on_display + Blockly.Msg.MIXLY_MICROBIT_IMAGE + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH + Blockly.Msg.blockpy_turtle_set_num); + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_ROTATION_ANGLE) + .appendField(new Blockly.FieldDropdown([ + ['0','0'], + ['90','90'], + ['180','180'], + ['270','270'] + ]),'angle'); + this.appendValueInput("w") + .appendField(Blockly.Msg.MIXLY_Enlarge_and_scale_to) + this.appendValueInput("h") + .appendField(Blockly.Msg.MIXLY_High_zoom_level_to) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_OPEN_IMAGE_TOOLTIP); + } +}; + +export const GET_IMAGE_FROM_NET = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('direct') + .appendField(Blockly.Msg.MIXLY_GET_IMAGE_FROM_NET); + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_ROTATION_ANGLE) + .appendField(new Blockly.FieldDropdown([ + ['0','0'], + ['90','90'], + ['180','180'], + ['270','270'] + ]),'angle'); + this.appendValueInput("w") + .appendField(Blockly.Msg.MIXLY_Enlarge_and_scale_to) + this.appendValueInput("h") + .appendField(Blockly.Msg.MIXLY_High_zoom_level_to) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_OPEN_IMAGE_TOOLTIP); + } +}; +export const CAMERA_LOOGOUT = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LOGOUT + Blockly.Msg.MIXLY_SMARTCAMERA) + this.setPreviousStatement(true,null); + this.setNextStatement(true,null) + this.setInputsInline(true); + } +}; + +export const GET_PICTURE_DATA_EXACT = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_PICTURE_DATA) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const GET_PICTURE_WIDTH_HEIGHT_DEVICE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SMARTCAMERA+Blockly.Msg.MIXLY_MICROBIT_IMAGE+Blockly.Msg.MIXLY_WIDTH,"get_pixel_width"], + [Blockly.Msg.MIXLY_SMARTCAMERA+Blockly.Msg.MIXLY_MICROBIT_IMAGE+Blockly.Msg.MIXLY_HEIGHT,"get_pixel_height"], + [Blockly.Msg.MIXLY_SMARTCAMERA+Blockly.Msg.MIXLY_MODEL_NUMBER,"get_sensor_name"] + ]),"kind") + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const CONVERT_IMAGE_TO_JPG = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + this.appendDummyInput() + .appendField(Blockly.Msg.A_TO_B) + .appendField(new Blockly.FieldDropdown([ + ["JPG" + Blockly.Msg.MIXLY_SD_DATA,"0"], + [Blockly.Msg.MIXLY_JPG_base64_CODE + Blockly.Msg.MIXLY_SD_DATA ,"1"] + ]),"kind"); + this.appendValueInput('quality') + .appendField(Blockly.Msg.MIXLY_IMAGE_QUALITY); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const GET_PICTURE_DATA_WHS = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_GET); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_WIDTH,"width"], + [Blockly.Msg.MIXLY_HEIGHT,"height"], + [Blockly.Msg.MIXLY_MICROBIT_JS_I2C_FORMAT,"format"] + ]),"kind") + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const SCREEN_SHOW_CAM_GRAPH_SHOOT = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.OLEDDISPLAY + Blockly.Msg.MIXLY_MICROBIT_IMAGE) + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const SCREEN_SHOW_CAM_GRAPH_SHOOT_LOCATION = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.OLEDDISPLAY + Blockly.Msg.MIXLY_MICROBIT_IMAGE) + this.appendValueInput("x") + .appendField(Blockly.Msg.TURTLE_POS + "x"); + this.appendValueInput("y") + .appendField("y") + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const SCREEN_DISPLAY_IMAGE = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('direct') + .appendField(Blockly.Msg.OLED_BITMAP) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH); + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_ROTATION_ANGLE) + .appendField(new Blockly.FieldDropdown([ + ['0','0'], + ['90','90'], + ['180','180'], + ['270','270'] + ]),'angle'); + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const SCREEN_DISPLAY_IMAGE_LOCATION = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('direct') + .appendField(Blockly.Msg.OLED_BITMAP) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH); + this.appendValueInput("x") + .appendField(Blockly.Msg.TURTLE_POS + "x"); + this.appendValueInput("y") + .appendField("y") + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_ROTATION_ANGLE) + .appendField(new Blockly.FieldDropdown([ + ['0','0'], + ['90','90'], + ['180','180'], + ['270','270'] + ]),'angle'); + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const GET_SCREEN_IMAGE_SIZE = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SCREENSHOT + Blockly.Msg.MIXLY_MICROBIT_monitor) + this.appendValueInput("x") + .appendField("x") + this.appendValueInput("y") + .appendField("y") + this.appendValueInput("w") + .appendField("w") + this.appendValueInput("h") + .appendField("h") + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_MICROBIT_IMAGE) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const GET_SCREEN_IMAGE = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_MICROBIT_monitor + Blockly.Msg.MIXLY_MICROBIT_IMAGE) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const AI_CAMERA_INIT = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_QR_CODE + Blockly.Msg.MIXLY_RECOGNITION, "QRReader"], + [Blockly.Msg.MIXLY_COLOR_RECOGNTITION, "ColorDetector"], + [Blockly.Msg.MIXLY_CAT + Blockly.Msg.MIXLY_RECOGNITION, "CatDetector"], + [Blockly.Msg.MIXLY_HUMAN + Blockly.Msg.MIXLY_RECOGNITION, "HumanDetector"], + [Blockly.Msg.MIXLY_FACE_CLASSIFIER, "FaceDetector"], + [Blockly.Msg.MIXLY_PICTURE_CLASSIFY,"ImageNet"] + ]), "kind"); + this.appendValueInput("WIDTH") + .appendField(Blockly.Msg.MIXLY_WIDTH); + this.appendValueInput("HEIGHT") + .appendField(Blockly.Msg.MIXLY_HEIGHT); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const MODEL_INIT_WIDTH = { + init: function(){ + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["240px","240"], + ["320px","320"], + ["128px","128"], + ["96px","96"], + ["640px","640"], + ["480px","480"], + ["160px","160"] + ]),"width"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const MODEL_INIT_HEIGHT = { + init: function(){ + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["240px","240"], + ["320px","320"], + ["128px","128"], + ["96px","96"], + ["480px","480"], + ["320px","320"], + ["240px","240"], + ["120px","120"] + ]),"height"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const AI_CAMERA_INIT_FACERECOGNIZE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(Blockly.Msg.MIXLY_AipFace); + this.appendValueInput("WIDTH") + .appendField(Blockly.Msg.MIXLY_WIDTH); + this.appendValueInput("HEIGHT") + .appendField(Blockly.Msg.MIXLY_HEIGHT); + this.appendValueInput("PATH") + .appendField(Blockly.Msg.PATH_OF_FACE_DATABASE); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const MODEL_LOGOUT = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LOGOUT) + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const MODEL_RUN = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendValueInput("FRAME") + .appendField(Blockly.Msg.MIXLY_RUN + Blockly.Msg.MIXLY_RECOGNITION_RECGNITION + Blockly.Msg.MIXLY_AipImageClassify_Image) + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const MODEL_WHETHER_RUN_SUCCEED = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_RECOGNITION_RECGNITION) + this.appendDummyInput("") + .appendField( Blockly.Msg.MIXLY_WHETHER + Blockly.Msg.MIXLY_SUCCESS) + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const GET_HOW_MUCH_RECOGNITION = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET +Blockly.Msg.MIXLY_HOW_MUCH) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_QR_CODE, "QRReader"], + [Blockly.Msg.HTML_COLOUR, "ColorDetector"], + [Blockly.Msg.MIXLY_CAT, "CatDetector"], + [Blockly.Msg.MIXLY_HUMAN, "HumanDetector"], + [Blockly.Msg.MIXLY_FACE, "FaceDetector"] + ]), "kind"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_BE_IDENTIFIED); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const GET_NO_RECOGNITION = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendValueInput("NO") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_QR_CODE, "QRReader"], + [Blockly.Msg.HTML_COLOUR, "ColorDetector"], + [Blockly.Msg.MIXLY_CAT, "CatDetector"], + [Blockly.Msg.MIXLY_HUMAN, "HumanDetector"], + [Blockly.Msg.MIXLY_FACE, "FaceDetector"], + [Blockly.Msg.MIXLY_PICTURE_CLASSIFY,"ImageNet"] + ]), "kind"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DE + Blockly.Msg.OLED_STRING); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const GET_NO_CAT_OR_FACE_RECOGNITION = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendValueInput("NO") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_QR_CODE, "QRReader"], + [Blockly.Msg.HTML_COLOUR, "ColorDetector"], + [Blockly.Msg.MIXLY_CAT, "CatDetector"], + [Blockly.Msg.MIXLY_HUMAN, "HumanDetector"], + [Blockly.Msg.MIXLY_FACE, "FaceDetector"], + [Blockly.Msg.MIXLY_PICTURE_CLASSIFY,"ImageNet"] + ]), "kind"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DE + Blockly.Msg.MIXLY_CONFIDENCE_DEGREE); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const GET_NO_XY_RECOGNITION = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendValueInput("NO") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_QR_CODE, "QRReader"], + [Blockly.Msg.HTML_COLOUR, "ColorDetector"], + [Blockly.Msg.MIXLY_CAT, "CatDetector"], + [Blockly.Msg.MIXLY_HUMAN, "HumanDetector"], + [Blockly.Msg.MIXLY_FACE, "FaceDetector"] + ]), "kind"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DE + Blockly.Msg.MIXLY_POSITION_XY) + .appendField(new Blockly.FieldDropdown([ + ["x","0"], + ["y","1"], + ["w","2"], + ["h","3"], + [Blockly.Msg.MIXLY_ALL + '(x,y,w,h)',"all"] + ]),"coord"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const GET_NO_XY_RECOGNITION_FACE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendValueInput("NO") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2) + .appendField(Blockly.Msg.MIXLY_FACE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DE + Blockly.Msg.MIXLY_POSITION_XY) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT_EYE + "x","[0]"], + [Blockly.Msg.MIXLY_LEFT_EYE + "y","[1]"], + [Blockly.Msg.MIXLY_RIGHT_EYE + "x","[2]"], + [Blockly.Msg.MIXLY_RIGHT_EYE + "y","[3]"], + [Blockly.Msg.MIXLY_NOSE + "x","[4]"], + [Blockly.Msg.MIXLY_NOSE + "y","[5]"], + [Blockly.Msg.MIXLY_LEFT_MOUSE_CORNER + "x","[6]"], + [Blockly.Msg.MIXLY_LEFT_MOUSE_CORNER + "y","[7]"], + [Blockly.Msg.MIXLY_RIGHT_MOUSE_CORNER + "x","[8]"], + [Blockly.Msg.MIXLY_RIGHT_MOUSE_CORNER + "y","[9]"], + [Blockly.Msg.MIXLY_ALL ,"all"] + ]),"part") + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const GET_NO_FACE_RECOGNITION_INFO = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendValueInput("NO") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.MIXLY_FACE + Blockly.Msg.MIXLY_DE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_FACE_ID,"id"], + [Blockly.Msg.MILXY_FACE_SIMILARITY,"similarity"], + [Blockly.Msg.MIXLY_FACE_NAME,"name"] + ]),"kind"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Register_color_recognition_fixed = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_REGISTER + Blockly.Msg.MIXLY_RECOGNITION_RECGNITION + Blockly.Msg.HTML_COLOUR) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_RED,"red"], + [Blockly.Msg.COLOUR_RGB_GREEN,"green"], + [Blockly.Msg.COLOUR_RGB_BLUE,"blue"], + [Blockly.Msg.COLOUR_YELLOW,"yellow"], + [Blockly.Msg.COLOUR_CYAN,"cyan"], + [Blockly.Msg.COLOUR_RGB_PURPLE,"purple"], + [Blockly.Msg.COLOUR_BLACK,"black"], + [Blockly.Msg.COLOUR_WHITE,"white"] + ]),"color"); + this.appendValueInput("AREA") + .appendField(Blockly.Msg.MINIMUN_DETECTABLE_AREA); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const Register_color_recognition = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.REGISTER_COLOR_RECOGNITION) + this.appendValueInput("MIN") + .appendField('H、S、V' + Blockly.Msg.blockpy_TUPLE_MIN); + this.appendValueInput("MAX") + .appendField('H、S、V' + Blockly.Msg.blockpy_TUPLE_MAX); + this.appendValueInput("COLOR") + .appendField(Blockly.Msg.HTML_COLOUR + Blockly.Msg.MIXLY_NAME) + this.appendValueInput("AREA") + .appendField(Blockly.Msg.MINIMUN_DETECTABLE_AREA); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const REGISTER_NEW_FACE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendValueInput('IMAGE') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE + Blockly.Msg.MIXLY_AipImageClassify_Image) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.register_a_new_face_in_the_database); + this.appendValueInput("NAME") + .appendField(Blockly.Msg.MICROPYTHON_HUSKYLENS_NAME); + this.setOutput(true) + this.setInputsInline(true); + } +}; + +export const DELETE_FACE_FROM_DATABASE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.delete_the_face_from_the_database); + this.appendValueInput("ID") + .appendField('id'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const DELETE_FACE_ALL = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_DELETE_VAR + Blockly.Msg.MIXLY_ALL + Blockly.Msg.MIXLY_FACE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const PRINT_FACE_DATABASE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.print_the_contents_of_the_face_database); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const GET_QR_CODE_RECOGNITION_DATA = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_QR_CODE_RECOGNITION_RESULT); + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const GET_PICTURE_RECOGNITION_DATA = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_PICTURE_CLASSIFY_RESULT); + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const GET_COLOR_DETECTION_NUM = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_HOW_MUCH + Blockly.Msg.MIXLY_REGISTER + Blockly.Msg.HTML_COLOUR ) + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setOutput(true); + this.setInputsInline(true); + // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); + } +}; + +// export const GET_COLOR_DETECTION_LOCATION = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendValueInput('NO') +// .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2) +// .appendField(new Blockly.FieldDropdown([ +// [Blockly.Msg.COLOUR_RGB_RED,"0"], +// [Blockly.Msg.COLOUR_RGB_ORANGE,"1"], +// [Blockly.Msg.COLOUR_RGB_YELLOW,"2"], +// [Blockly.Msg.COLOUR_RGB_GREEN,"3"], +// [Blockly.Msg.COLOUR_RGB_CYAN,"4"], +// [Blockly.Msg.COLOUR_RGB_BLUE,"5"], +// [Blockly.Msg.COLOUR_RGB_PURPLE,"6"], +// [Blockly.Msg.COLOUR_RGB_WHITE,"7"], +// [Blockly.Msg.COLOUR_RGB_GREY,"8"], +// [Blockly.Msg.MIXLY_CUSTOM_STUDY,"9"] +// ]),'color'); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_Pixel_block + Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_POSITION_XY); +// this.setOutput(true); +// this.setInputsInline(true); +// // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); +// } +// }; + +export const GET_CAT_FACE_DETECTION_NUM = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_HOW_MUCH +Blockly.Msg.MIXLY_CAT) + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setOutput(true); + this.setInputsInline(true); + // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); + } +}; + +// export const GET_CAT_FACE_DETECTION_LOCATION = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendValueInput('NO') +// .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.MIXLY_CAT_FACE + Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_POSITION_XY); +// this.setOutput(true); +// this.setInputsInline(true); +// // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); +// } +// }; + +export const GET_HUMAN_DETECTION_NUM = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_HOW_MUCH +Blockly.Msg.MIXLY_HUMAN) + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setOutput(true); + this.setInputsInline(true); + // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); + } +}; + +export const GET_FACE_DETECTION_NUM = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_HOW_MUCH +Blockly.Msg.MIXLY_FACE) + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setOutput(true); + this.setInputsInline(true); + // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); + } +}; + +export const GET_FACE_DETECTION_NAME = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_AipFace +Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_NAME) + this.appendValueInput('boolean') + .appendField( Blockly.Msg.MIXLY_synchronize); + this.setOutput(true); + this.setInputsInline(true); + // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); + } +}; + +// export const GET_FACE_DETECTION_LOCATION = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendValueInput('NO') +// .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.MIXLY_FACE + Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_POSITION_XY); +// this.setOutput(true); +// this.setInputsInline(true); +// // this.setTooltip(Blockly.Msg.MIXLY_GET_COLOR_DETECTION_RESULT_TOOLTIP); +// } +// }; + +// export const GET_FACE_DETECTION_KEYPOINT_LOCATION = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendValueInput('NO') +// .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.MIXLY_FACE); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_KEYPOINT) +// .appendField(new Blockly.FieldDropdown([ +// [Blockly.Msg.MIXLY_LEFT_EYE,"0"], +// [Blockly.Msg.MIXLY_RIGHT_EYE,"1"], +// [Blockly.Msg.MIXLY_NOSE,"2"], +// [Blockly.Msg.MIXLY_LEFT_MOUSE_CORNER,"3"], +// [Blockly.Msg.MIXLY_RIGHT_MOUSE_CORNER,"4"] +// ]),'kp') +// .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_POSITION_XY); +// this.setOutput(true); +// this.setInputsInline(true); +// } +// }; + +// export const GET_FACE_RECOGNITION_ID = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_RECOGNITION_RECGNITION + Blockly.Msg.MIXLY_FACE + 'ID'); +// this.setOutput(true); +// this.setInputsInline(true); +// } +// }; + +// export const GET_FACE_RECOGNITION_ID_LOCATION = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendValueInput('NO') +// .appendField(Blockly.Msg.MIXLY_GET +'ID'+ Blockly.Msg.MIXLY_AS); +// this.appendDummyInput() +// .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_FACE + Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_POSITION_XY); +// this.setOutput(true); +// this.setInputsInline(true); +// } +// }; + +// export const GET_FACE_RECOGNITION_ID_KEYPOINT_LOCATION = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendValueInput('NO') +// .appendField(Blockly.Msg.MIXLY_GET + 'ID'+ Blockly.Msg.MIXLY_AS); +// this.appendDummyInput() +// .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_FACE); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_KEYPOINT) +// .appendField(new Blockly.FieldDropdown([ +// [Blockly.Msg.MIXLY_LEFT_EYE,"0"], +// [Blockly.Msg.MIXLY_RIGHT_EYE,"1"], +// [Blockly.Msg.MIXLY_NOSE,"2"], +// [Blockly.Msg.MIXLY_LEFT_MOUSE_CORNER,"3"], +// [Blockly.Msg.MIXLY_RIGHT_MOUSE_CORNER,"4"] +// ]),'kp') +// .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_POSITION_XY); +// this.setOutput(true); +// this.setInputsInline(true); +// } +// }; + +// export const PEOPLE_FACE_ENROLL = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendDummyInput() +// .appendField(Blockly.Msg.FACE_ENROLL); +// this.setOutput(true); +// this.setInputsInline(true); +// } +// }; + +// export const DELETE_PEOPLE_FACE_ID= { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendValueInput("ID") +// .appendField(Blockly.Msg.MIXLY_DELETE_PEOPLE_FACE_ID); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// this.setInputsInline(true); +// } +// }; + +// export const MODELP_SIMPLELY_RUN_RECOGNIZION = { +// init: function () { +// this.setColour(AI_LOCAL_GRAPH_HUE); +// this.appendValueInput('SUB') +// .appendField(Blockly.Msg.MIXLY_RUN + Blockly.Msg.MIXLY_TENSORFLOW_MODEL + Blockly.Msg.MIXLY_RECOGNITION_RECGNITION) +// .setCheck("var"); +// this.appendValueInput('CAM') +// .setCheck("var"); + +// this.appendDummyInput("") +// .appendField(new Blockly.FieldDropdown([ +// [Blockly.Msg.MIXPY_AI_RESULT,"data"], +// [Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_HOW_MUCH + Blockly.Msg.MIXPY_OBJECT,"len"], +// [Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_AipFace + Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_NAME,"person"] +// ]),"key") +// this.appendValueInput('VAR') +// .appendField(Blockly.Msg.HTML_COLOUR) +// this.appendValueInput('boolean') +// .appendField( Blockly.Msg.MIXLY_synchronize); +// this.setOutput(true); +// this.setInputsInline(true); +// } +// }; + + + + + + +export const AI_STOP_ACQUISITION = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_STOP) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IMAGE_ACQUISITION); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const MIXIO_REPORT_IMAGE_DATA = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET +Blockly.Msg.MIXLY_IMAGE_OF_FILE) + this.appendValueInput('SUB'); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +//simplified part +export const CREATE_CAMERA_SIMPLE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_SMARTCAMERA) + .appendField(Blockly.Msg.MIXLY_SHOOTING_SIZE) + .appendField(new Blockly.FieldDropdown([ + ['240px*240px', "R240X240"], + ['320px*320px', "R320X320"], + ['128px*128px', "R128X128"], + ['96px*96px', "R96X96"], + ['VGA : 640px*480px', "VGA"], + ['HVGA : 480px*320px', "HVGA"], + ['QVGA : 320px*240px', "QVGA"], + ['QQVGA : 160px*120px', "QQVGA"] + ]), "cmd"); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const AI_CAMERA_INIT_SIMPLE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_QR_CODE + Blockly.Msg.MIXLY_RECOGNITION, "QRReader"], + [Blockly.Msg.MIXLY_COLOR_RECOGNTITION, "ColorDetector"], + [Blockly.Msg.MIXLY_CAT + Blockly.Msg.MIXLY_RECOGNITION, "CatDetector"], + [Blockly.Msg.MIXLY_HUMAN + Blockly.Msg.MIXLY_RECOGNITION, "HumanDetector"], + [Blockly.Msg.MIXLY_FACE_CLASSIFIER, "FaceDetector"], + [Blockly.Msg.MIXLY_AipFace,"FaceRecognizer"], + [Blockly.Msg.MIXLY_PICTURE_CLASSIFY,"ImageNet"] + ]), "kind"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const Register_color_recognition_fixed_SIMPLE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_REGISTER + Blockly.Msg.MIXLY_RECOGNITION_RECGNITION + Blockly.Msg.HTML_COLOUR) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.COLOUR_RGB_RED,"red"], + [Blockly.Msg.COLOUR_RGB_GREEN,"green"], + [Blockly.Msg.COLOUR_RGB_BLUE,"blue"], + [Blockly.Msg.COLOUR_YELLOW,"yellow"], + [Blockly.Msg.COLOUR_CYAN,"cyan"], + [Blockly.Msg.COLOUR_RGB_PURPLE,"purple"], + [Blockly.Msg.COLOUR_BLACK,"black"], + [Blockly.Msg.COLOUR_WHITE,"white"] + ]),"color"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const REGISTER_NEW_FACE_SIMPLE = { + init: function () { + this.setColour(AI_LOCAL_GRAPH_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TENSORFLOW_MODEL) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE + Blockly.Msg.MIXLY_SMARTCAMERA + Blockly.Msg.MIXLY_GET + + Blockly.Msg.register_a_new_face_in_the_database); + this.appendValueInput("NAME") + .appendField(Blockly.Msg.MICROPYTHON_HUSKYLENS_NAME); + this.setOutput(true) + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/ai_sensor.js b/mixly/boards/default_src/micropython/blocks/ai_sensor.js new file mode 100644 index 00000000..92c525aa --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/ai_sensor.js @@ -0,0 +1,749 @@ +import * as Blockly from 'blockly/core'; + +const AI_SENSOR_HUE = '#90A244'; //'#9e77c9'//40; + + +export const ai_sensor_use_uart_init = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "uart") + .appendField(new Blockly.FieldDropdown([ + ["uart1", "uart1"], + ["uart2", "uart2"] + ]), "key"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO + 'MixGo AI' + Blockly.Msg.MSG.catSensor) + + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const ai_sensor_qrcode = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_QR_CODE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.OLED_STRING, "info1"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_X_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "xc"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_Y_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "yc"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_QR_CODE_TOOLTIP); + } +}; + +export const ai_sensor_qrcode_lite = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_QR_CODE + Blockly.Msg.MIXPY_OBJECT, "qrcode"], + [Blockly.Msg.MIXLY_BAR_CODE + Blockly.Msg.MIXPY_OBJECT, "barcode"], + [Blockly.Msg.MIXLY_TAG + Blockly.Msg.MIXPY_OBJECT, "apriltag"] + ]), "TYPE"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ANALYSIS_RESULT); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(); + } +}; + +export const ai_sensor_find_qrcodes = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_QR_CODE_RECOGNTITION); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[qrcode]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_QR_CODE_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_config = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendValueInput("RX") + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_ETHERNET_CLINET_PORT) + .appendField("RX#") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("TX") + .appendField("TX#") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .appendField(Blockly.Msg.SOFT_RESET + Blockly.Msg.MIXLY_ESP32_RGB_WRITE) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_TRUE, 'True'], [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_FALSE, 'False']]), 'mode') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_CONFIG_TOOLTIP); + } +}; + +export const ai_sensor_rgb = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendValueInput("led1") + .appendField(Blockly.Msg.MIXLY_SETTING) + .appendField("RGB1") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("led2") + .appendField("RGB2") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_CONFIG_TOOLTIP); + } +}; + +export const ai_sensor_barcode = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_BAR_CODE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.OLED_STRING, "info1"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_X_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "xc"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_Y_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "yc"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_BAR_CODE_TOOLTIP); + } +}; + +export const ai_sensor_find_barcodes = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BAR_CODE_RECOGNTITION); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[barcode]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_BAR_CODE_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_tag = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_TAG + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.OLED_STRING, "info1"], + [Blockly.Msg.blockpy_turtle_rotate + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, "info2"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_X_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "xc"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_Y_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "yc"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_TAG_TOOLTIP); + } +}; + +export const ai_sensor_find_tags = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TAG_RECOGNTITION); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[tag]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_TAG_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_line = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_LINE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LINE_ANGLE, "info1"], + [Blockly.Msg.MIXLY_POSITION_XY + "-x1x2y1y2", "rect"], + ["x1" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["x2" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["y1" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["y2" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_LINE_TOOLTIP); + } +}; + +export const ai_sensor_find_lines = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LINE_RECOGNTITION); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_ESP32_THRESHOLD) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXLY_LINE_RECOGNTITION_ANGLE) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR3") + .appendField(Blockly.Msg.MIXLY_LINE_RECOGNTITION_SLOPE) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[line]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_LINE_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_circle = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_CIRCLE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_CIRCLE_AREA, "info1"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_X_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "xc"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_Y_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "yc"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_CIRCLE_TOOLTIP); + } +}; + +export const ai_sensor_find_circles = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CIRCLE_RECOGNTITION); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_ESP32_THRESHOLD) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXLY_CIRCLE_RECOGNTITION_MIN) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR3") + .appendField(Blockly.Msg.MIXLY_CIRCLE_RECOGNTITION_MAX) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[circle]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_CIRCLE_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_rect = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_RECT + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_CIRCLE_AREA, "info1"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_X_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "xc"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_Y_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "yc"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_RECT_TOOLTIP); + } +}; + +export const ai_sensor_find_rects = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RECT_RECOGNTITION); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_ESP32_THRESHOLD) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[rect]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_COLOR_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_color = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COLOR_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + ['RGB' + Blockly.Msg.HTML_COLOUR, "[0]"], + ['LAB' + Blockly.Msg.MIXLY_COLOR_LAB, "[1]"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_COLOR_TOOLTIP); + } +}; + +export const ai_sensor_find_colors = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COLOR_RECOGNTITION); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "color"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_COLOR_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_color_chases_result = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_CIRCLE_AREA, "info1"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_X_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "xc"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_Y_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "yc"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_CIRCLE_TOOLTIP); + } +}; + +export const ai_sensor_color_chases = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE); + this.appendValueInput("VAR1") + .appendField('LAB' + Blockly.Msg.MIXLY_COLOR_LAB) + + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXLY_ESP32_THRESHOLD) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR3") + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_MERGE) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[colors]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_CIRCLE_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_ailocal_train = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LOCAL_TRAIN) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_OBJECT_LIST) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MICROPYTHON_HUSKYLENS_SAVE_AS + Blockly.Msg.MIXLY_MODEL_NAME) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR3") + .appendField(Blockly.Msg.MIXLY_TRAIN_TIME) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR4") + .appendField(Blockly.Msg.MIXLY_AipNlp_Topic_Title) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(false); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_LOCAL_TRAIN_TOOLTIP); + } +}; + +export const ai_sensor_ailocal_class = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LOCAL_CLASS) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_OBJECT_LIST) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXLY_MODEL_NAME) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR4") + .appendField(Blockly.Msg.MIXLY_AipNlp_Topic_Title) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[objects]"); + this.setOutput(true); + this.setInputsInline(false); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_MODEL_NAME_TOOLTIP); + } +}; + +export const ai_sensor_ailocal_class_result = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_LOCAL_CLASS + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + ['ID', "info1"], + [Blockly.Msg.MIXLY_CONFIDENCE_DEGREE, "info2"], + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_LOCAL_CLASS_TOOLTIP); + } +}; + +export const ai_sensor_audio_record = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MUSIC_RECORD); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXPY_AI_AUDIO_TIME) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_MUSIC_RECORD_TOOLTIP); + } +}; + +export const ai_sensor_audio_play = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MUSIC_PLAY); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXLY_MP3_VOL) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .appendField('%') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + + } +}; + +export const ai_sensor_yolo_recognize = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_YOLO_RECOGNIZE) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_ANCHOR) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXLY_MODEL_PATH) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR4") + .appendField(Blockly.Msg.MIXLY_AipNlp_Topic_Title) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[objects]"); + this.setOutput(true); + this.setInputsInline(false); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_YOLO_RECOGNIZE_TOOLTIP); + } +}; + +export const ai_sensor_yolo_recognize_result = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_YOLO_RECOGNIZE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COLOR_CHASE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + ['ID', "info1"], + [Blockly.Msg.MIXLY_CONFIDENCE_DEGREE, "info2"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_X_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "xc"], + [Blockly.Msg.MICROPYTHON_HUSKYLENS_Y_CENTERED + Blockly.Msg.MIXLY_POSITION_XY, "yc"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_YOLO_RECOGNIZE_RESULT_TOOLTIP); + } +}; + +export const ai_sensor_asr_recognize = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr); + this.appendValueInput("VAR1") + .appendField(Blockly.Msg.MIXLY_AI_SENSOR_ASR_RECOGNISE_CORPUS) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("VAR2") + .appendField(Blockly.Msg.MIXLY_ESP32_THRESHOLD) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_ASR_RECOGNISE_TOOLTIP); + } +}; + +export const ai_sensor_licenseplate = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_LICENSEPLATE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + ['ID', "info1"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_LICENSEPLATE_TOOLTIP); + } +}; + +export const ai_sensor_find_licenseplates = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_AipOcr_licensePlate); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[licensePlate]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_LICENSEPLATE_RECOGNTITION_TOOLTIP); + } +}; + +export const ai_sensor_face = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_FACE + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + ["ID", "info1"], + [Blockly.Msg.MIXLY_CONFIDENCE_DEGREE, "info2"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_FACE_TOOLTIP); + } +}; + +export const ai_sensor_classifier_faces = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_AipFace); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[face]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_BAR_FACE_CLASSIFIER_TOOLTIP); + } +}; + +export const ai_sensor_20object = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_20OBJECTS + Blockly.Msg.MIXPY_OBJECT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ALL_CODE_ANALYSIS); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + ['ID', "info1"], + [Blockly.Msg.MIXLY_CONFIDENCE_DEGREE, "info2"], + [Blockly.Msg.MIXLY_POSITION_XY + "-xywh", "rect"], + ["x" + Blockly.Msg.MIXLY_POSITION_XY, "rect[0]"], + ["y" + Blockly.Msg.MIXLY_POSITION_XY, "rect[1]"], + ["w" + Blockly.Msg.MIXLY_POSITION_XY, "rect[2]"], + ["h" + Blockly.Msg.MIXLY_POSITION_XY, "rect[3]"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_20OBJECTS_TOOLTIP); + } +}; + +export const ai_sensor_find_20objects = { + init: function () { + this.setColour(AI_SENSOR_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_FIND_20OBJECTS); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + "[20objects]"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_AI_SENSOR_BAR_FIND_20OBJECTS_TOOLTIP); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/blynk.js b/mixly/boards/default_src/micropython/blocks/blynk.js new file mode 100644 index 00000000..35a9fc3f --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/blynk.js @@ -0,0 +1,368 @@ +import * as Blockly from 'blockly/core'; + +/******************* Blynk *****************/ +const BLYNK_HUE = '#2FAD7A'; + + +// 自定义终端部件 Terminal Blynk +export const mpython_blynk_terminal_widget_vpin = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_TERMINAL_WIDGET_VPIN_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_TERMINAL_WIDGET_VPIN_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_TERMINAL_WIDGET_VPIN_MESSAGE0, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "virtual_pin" + } + ] + }); + } +}; + +// 同步虚拟管脚的状态 Blynk +export const mpython_blynk_sync_virtual = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_SYNC_VIRTUAL_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_SYNC_VIRTUAL_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_SYNC_VIRTUAL_MESSAGE0, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "virtual_pin" + } + ] + }); + } +}; + +// 斷開连接 Blynk +export const mpython_blynk_on_disconnected = { + init: function () { + this.jsonInit({ + "inputsInline": true, + // "nextStatement": null, + // "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_ON_DISCONNECTED_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_ON_DISCONNECTED_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_ON_DISCONNECTED_MESSAGE0 + }); + this.appendStatementInput('DO') + .appendField(Blockly.CONTROLS_REPEAT_INPUT_DO); + } +}; + +// 连接上 Blynk +export const mpython_blynk_on_connected = { + init: function () { + this.jsonInit({ + "inputsInline": true, + // "nextStatement": null, + // "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_ON_CONNECTED_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_ON_CONNECTED_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_ON_CONNECTED_MESSAGE0 + }); + this.appendStatementInput('DO') + .appendField(Blockly.CONTROLS_REPEAT_INPUT_DO); + } +}; + +// Blynk 定时器的进程生效并运行 +export const mpython_blynktimer_run = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNKTIMER_RUN_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNKTIMER_RUN_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNKTIMER_RUN_MESSAGE0 + }); + } +}; + +// Blynk 进程生效并运行 +export const mpython_blynk_run = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_RUN_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_RUN_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_RUN_MESSAGE0 + }); + } +}; + +// Blynk APP 显示通知 +export const mpython_blynk_app_notify = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_APP_NOTIFY_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_APP_NOTIFY_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_APP_NOTIFY_MESSAGE0, + "args0": [ + { + "check": String, + "type": "input_value", + "name": "notification" + } + ] + }); + } +}; + +// 停止 Blynk 定时器 %1 +export const mpython_blynk_stop_timers = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + // "output": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_STOP_TIMERS_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNKTIMER_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_STOP_TIMERS_MESSAGE0, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "timer_num" + } + ] + }); + } +}; + +// 给虚拟管脚添加 属性 %1 值 %2 +export const mpython_blynk_set_property = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + // "output": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_SET_PROPERTY_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_SET_PROPERTY_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_SET_PROPERTY_MESSAGE0, + "args0": [ + { + "check": String, + "type": "input_value", + "name": "attribute_name" + } + , + { + // "check":String, + "type": "input_value", + "name": "attribute_value" + } + ] + }); + } +}; + +// 向 %1 发邮件 主题 %2 正文 %3 +export const mpython_blynk_email = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + // "output": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_EMAIL_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_EMAIL_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_EMAIL_MESSAGE0, + "args0": [ + { + "check": String, + "type": "input_value", + "name": "TargetEmail" + } + , + { + "check": String, + "type": "input_value", + "name": "subject" + } + , + { + "check": String, + "type": "input_value", + "name": "body" + } + ] + }); + } +}; + +// 可用的 Blynk 定时器 +export const mpython_blynk_get_timers = { + init: function () { + this.jsonInit({ + "inputsInline": true, + // "nextStatement": null, + // "previousStatement": null, + "output": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_GET_TIMERS_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_GET_TIMERS_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_GET_TIMERS_MESSAGE0, + }); + } +}; + +//blynk定时器 +export const mpython_blynktimer = { + init: function () { + this.jsonInit({ + "message0": Blockly.Msg.MPYTHON_BLYNKTIMER_MESSAGE0, + // "nextStatement": null, + // "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNKTIMER_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNKTIMER_TOOLTIP, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "Num" + } + , + { + "options": [ + [Blockly.Msg.MIXLY_PYTHON_PERIODIC, 'False'], + [Blockly.Msg.MIXLY_PYTHON_ONE_SHOT, 'True'] + ], + "type": "field_dropdown", + "name": "Timer_mode" + } + , + { + "check": Number, + "type": "input_value", + "name": "period" + } + ] + }); + this.appendStatementInput('DO') + .appendField(Blockly.CONTROLS_REPEAT_INPUT_DO); + } +}; + +// 发送数据 %1 到 Bylnk APP 的虚拟管脚 %2 +export const mpython_blynk_sensor_data_to_app = { + init: function () { + this.jsonInit({ + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_SENSOR_DATA_TO_APP_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_SENSOR_DATA_TO_APP_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_SENSOR_DATA_TO_APP_MESSAGE0, + "args0": [ + { + "type": "input_value", + "name": "sensor_data" + } + , + { + "check": Number, + "type": "input_value", + "name": "virtual_pin" + } + ] + }); + } +}; + +// 从 Bylnk APP 获取虚拟管脚 %1 的值 +export const mpython_blynk_app_data = { + init: function () { + this.jsonInit({ + "inputsInline": true, + // "nextStatement": null, + // "previousStatement": null, + // "output":null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_APP_DATA_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_SENSOR_DATA_TO_APP_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_APP_DATA_MESSAGE0, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "virtual_pin" + } + , + { + "type": "input_value", + "name": "virtual_pin_val" + } + ] + }); + this.appendStatementInput('DO') + .appendField(Blockly.CONTROLS_REPEAT_INPUT_DO); + } +}; + +// Bylnk设置 +export const mpython_blynk_setup = { + init: function () { + this.jsonInit({ + // "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "colour": BLYNK_HUE, + "helpUrl": Blockly.Msg.MPYTHON_BLYNK_SETUP_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_BLYNK_SETUP_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_BLYNK_SETUP_MESSAGE0, + "args0": [ + { + "type": "input_dummy" + }, + { + "check": String, + "type": "input_value", + "name": "server" + }, + { + "check": Number, + "type": "input_value", + "name": "port" + }, + { + "check": String, + "type": "input_value", + "name": "auth" + } + ] + }); + } +}; diff --git a/mixly/boards/default_src/micropython/blocks/cc_g1.js b/mixly/boards/default_src/micropython/blocks/cc_g1.js new file mode 100644 index 00000000..8e36fad7 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/cc_g1.js @@ -0,0 +1,81 @@ +import * as Blockly from 'blockly/core'; + +const CCG1_HUE = 40; + +export const cc_g1_init = { + init: function () { + this.setColour(CCG1_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + " CC_G1"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "temperature": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_temperature_TOOLTIP, + "relative_humidity": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_HUM_TOOLTIP + }; + return TOOLTIPS[mode] + }); + } +}; + +export const cc_g1_read_bat = { + init: function () { + this.setColour(CCG1_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET_BATTERY); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const cc_g1_read_joystick = { + init: function () { + this.setColour(CCG1_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_JOYSTICK) + .appendField(new Blockly.FieldDropdown([ + ["x", "[0]"], + ["y", "[1]"], + ["(x,y)", ""] + ]), "VAR"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DATA); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const cc_g1_read_key = { + init: function () { + this.setColour(CCG1_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(new Blockly.FieldDropdown([ + ["A", "0"], + ["B", "1"], + ["C", "2"], + ["D", "3"], + ["POWER", "4"], + ["SELECT", "5"] + ]), "VAR"); + this.appendDummyInput("") + .appendField(Blockly.Msg.WHETHER_IS_PRESSED); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const cc_g1_turnoff = { + init: function () { + this.setColour(CCG1_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_HANDLE_SHUTDOWN); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; diff --git a/mixly/boards/default_src/micropython/blocks/ce_go.js b/mixly/boards/default_src/micropython/blocks/ce_go.js new file mode 100644 index 00000000..58f24bb4 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/ce_go.js @@ -0,0 +1,395 @@ +import * as Blockly from 'blockly/core'; + +const MEGO_HUE = 100; + +//LED +export const ce_go_light_number = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXGO_LEFT_FRONT + Blockly.Msg.COLOUR_RGB_GREEN + Blockly.Msg.MIXLY_EXTERN_LED, "GLED[0]"], + [Blockly.Msg.MIXGO_RIGHT_FRONT + Blockly.Msg.COLOUR_RGB_GREEN + Blockly.Msg.MIXLY_EXTERN_LED, "GLED[1]"], + [Blockly.Msg.MIXGO_LEFT_BACK + Blockly.Msg.COLOUR_RGB_GREEN + Blockly.Msg.MIXLY_EXTERN_LED, "GLED[3]"], + [Blockly.Msg.MIXGO_RIGHT_BACK + Blockly.Msg.COLOUR_RGB_GREEN + Blockly.Msg.MIXLY_EXTERN_LED, "GLED[2]"], + [Blockly.Msg.MIXGO_LEFT_FRONT + Blockly.Msg.COLOUR_RGB_RED + Blockly.Msg.MIXLY_EXTERN_LED, "RLED[0]"], + [Blockly.Msg.MIXGO_RIGHT_FRONT + Blockly.Msg.COLOUR_RGB_RED + Blockly.Msg.MIXLY_EXTERN_LED, "RLED[1]"], + [Blockly.Msg.MIXGO_LEFT_BACK + Blockly.Msg.COLOUR_RGB_RED + Blockly.Msg.MIXLY_EXTERN_LED, "RLED[3]"], + [Blockly.Msg.MIXGO_RIGHT_BACK + Blockly.Msg.COLOUR_RGB_RED + Blockly.Msg.MIXLY_EXTERN_LED, "RLED[2]"], + [Blockly.Msg.ME_GO_LIGHT_HEADLIGHT, "WLED"] + ]), 'op') + this.setOutput(true); + } +}; + +export const ce_go_led_bright = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('led') + .appendField('ME GO') + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_SETONOFF); + } +}; + +export const ce_go_get_led_bright = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendValueInput('led') + .appendField('ME GO') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + +export const ce_go_get_led_state = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendValueInput('led') + .appendField('ME GO') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_LED_GETONOFF); + } +}; + +export const ce_go_led_brightness = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING); + this.appendValueInput('led') + .appendField('ME GO') + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_BRIGHTNESS) + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_BUILDIN_LED + Blockly.Msg.MIXLY_BRIGHTNESS + '(0-10)'); + } +}; + + +export const ce_go_stepper_keep = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField("ME GO") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.blockpy_forward, "F"], + [Blockly.Msg.blockpy_backward, "B"], + [Blockly.Msg.blockpy_left, "L"], + [Blockly.Msg.blockpy_right, "R"] + ]), "VAR"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const ce_go_stepper_stop = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField("ME GO") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "VAR"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const ce_go_dc_motor = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField("ME GO") + .appendField(Blockly.Msg.MOTOR_DC) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLYCAR_WHEEL_LEFT, "0"], + [Blockly.Msg.MIXLYCAR_WHEEL_RIGHT, "1"], + [Blockly.Msg.ME_GO_MOTOR_EXTERN, "2"] + ]), "wheel"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.ROTATION_FORWARD, "CW"], + [Blockly.Msg.ROTATION_BACKWARD, "CCW"], + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const ce_go_hall_attachInterrupt = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_INTERRUPT) + .appendField(Blockly.Msg.ME_GO_HALL_SENSOR) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.TEXT_TRIM_LEFT, "A"], [Blockly.Msg.TEXT_TRIM_RIGHT, "B"]]), "mode"); + this.appendValueInput('DO') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const ce_go_hall_initialize = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.ME_GO_HALL_SENSOR) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.TEXT_TRIM_LEFT, "A"], [Blockly.Msg.TEXT_TRIM_RIGHT, "B"]]), "mode"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([['turns', "turns"], ['distance', "distance"], ['turns,distance', 'all']]), "args"); + this.appendValueInput('num') + .setCheck(Number) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const ce_go_hall_data = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.ME_GO_HALL_SENSOR) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.TEXT_TRIM_LEFT, "A"], [Blockly.Msg.TEXT_TRIM_RIGHT, "B"]]), "mode"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([['turns', "turns"], ['distance', "distance"], ['speed', 'speed']]), "args"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const ce_go_pin_near_line = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "[0]"], + [Blockly.Msg.MIXGO_LEFT_MID, "[1]"], + [Blockly.Msg.MIXGO_RIGHT_MID, "[2]"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "[3]"], + [Blockly.Msg.MIXLY_ALL, ""] + ]), "key") + .appendField(Blockly.Msg.MIXGO_LINE_SENSOR_VAL); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(function () { + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + return mode0 + mode1 + }); + } +}; + +export const ce_go_pin_near = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXGO_LEFT_FRONT, "[0]"], + [Blockly.Msg.MIXGO_RIGHT_FRONT, "[1]"], + [Blockly.Msg.MIXGO_LEFT_BACK, "[3]"], + [Blockly.Msg.MIXGO_RIGHT_BACK, "[2]"], + [Blockly.Msg.MIXLY_ALL, ""] + ]), "key") + .appendField(Blockly.Msg.MIXGO_PROXIMITY_SENSOR); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(function () { + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + return mode0 + mode1 + }); + } +}; + +export const ce_go_pin_near_state_change = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_CAR_SENSOR_ONBOARD_CHANGE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ME_GO_CAR_SENSOR_ONBOARD_AUTO_CHANGE, "AS"], + [Blockly.Msg.MIXLY_MIXGO_CAR_USE_LINE_ONLY, "LP"], + [Blockly.Msg.MIXLY_MIXGO_CAR_USE_PROXIMITY_ONLY, "OA"], + [Blockly.Msg.MIXLY_ME_GO_CAR_LIGHT_SEEKING_ONLY, "LS"], + [Blockly.Msg.ME_GO_SENSOR_MODE_OFF, "CL"] + ]), "key"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const sensor_mixgome_eulerangles = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET_GESTURE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.ME_GO_PITCH, '[0]'], + [Blockly.Msg.ME_GO_ROLL, '[1]'], + [Blockly.Msg.ME_GO_PITCH + ', ' + Blockly.Msg.ME_GO_ROLL, ''] + ]), 'angle'); + // this.appendDummyInput("") + // .appendField(Blockly.Msg.BOARD_DIRECTION) + // .appendField(new Blockly.FieldDropdown([ + // [Blockly.Msg.OLED_VER,'True'], + // [Blockly.Msg.OLED_HOR,'False'], + // ]),'dir'); + this.appendDummyInput("") + this.setOutput(true, Number); + this.setInputsInline(true); + + } +}; + +export const ce_go_pin_light = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "[0]"], + [Blockly.Msg.MIXGO_LEFT_MID, "[1]"], + [Blockly.Msg.MIXGO_RIGHT_MID, "[2]"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "[3]"], + [Blockly.Msg.MIXLY_ALL, ""] + ]), "key") + .appendField(Blockly.Msg.MIXLY_ME_GO_CAR_LIGHT_SEEKING_SENSOR); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(function () { + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ME_GO_CAR_LIGHT_SEEKING_SENSOR; + return mode0 + mode1 + }); + } +}; + +//educore car +export const educore_car = { + init: function () { + this.setColour(MEGO_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CAR); + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const educore_car_stepper_keep = { + init: function () { + this.setColour(MEGO_HUE); + this.appendValueInput('car'); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.blockpy_forward, "forward"], + // [Blockly.Msg.blockpy_backward, "B"], + [Blockly.Msg.blockpy_left, "turn_left"], + [Blockly.Msg.blockpy_right, "turn_right"] + ]), "VAR"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_SPEED); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const educore_car_stepper_stop = { + init: function () { + this.setColour(MEGO_HUE); + this.appendValueInput('car'); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MOTOR_P, "stop"] + // [Blockly.Msg.MOTOR_N, "N"] + ]), "VAR"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const educore_car_pin_near_line = { + init: function () { + this.setColour(MEGO_HUE); + this.appendValueInput('car'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "1"], + // [Blockly.Msg.MIXGO_LEFT_MID, "[1]"], + // [Blockly.Msg.MIXGO_RIGHT_MID, "[2]"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "2"] + // [Blockly.Msg.MIXLY_ALL, ""] + ]), "key") + .appendField(Blockly.Msg.MIXGO_LINE_SENSOR_VAL); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const educore_car_pin_near = { + init: function () { + this.setColour(MEGO_HUE); + this.appendValueInput('car'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXGO_PROXIMITY_SENSOR); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/communicate.js b/mixly/boards/default_src/micropython/blocks/communicate.js new file mode 100644 index 00000000..c7dde5a0 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/communicate.js @@ -0,0 +1,1178 @@ +import * as Blockly from 'blockly/core'; + +const COMMUNICATE_HUE = 140 + +export const communicate_i2c_onboard = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LED_ON_BOARD + "I2C"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const communicate_spi_onboard = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LED_ON_BOARD + "SPI"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const communicate_i2c_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('SUB') + .appendField("I2C " + Blockly.Msg.MIXLY_SETUP) + .setCheck("var"); + + this.appendValueInput("TX", Number) + .appendField("SCL") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("RX", Number) + .appendField("SDA") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('freq') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_I2C_INIT); + } +}; + +export const communicate_i2c_read = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .appendField("I2C") + .setCheck("var"); + this.appendValueInput('address') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_RNUMBER); + this.appendValueInput('data') + .setCheck(Number) + .appendField(Blockly.Msg.LANG_MATH_BYTE); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_READ); + } +} + +export const communicate_i2c_write = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .appendField("I2C") + .setCheck("var"); + this.appendValueInput('address') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_WNUMBER); + this.appendValueInput('data') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_VALUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_WRITE); + } +} + +export const communicate_i2c_scan = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .appendField("I2C") + .setCheck("var") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_I2C_SCAN1 + Blockly.Msg.MIXLY_ESP32_I2C_SCAN2) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_I2C_SCAN); + } +} + +export const communicate_spi_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField(Blockly.Msg.MIXLY_ESP32_SPI_INIT); + this.appendValueInput('freq') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SERIAL_BEGIN); + this.appendValueInput('sck') + .setCheck(Number) + .appendField('SCK'); + this.appendValueInput('mosi') + .setCheck(Number) + .appendField('MOSI'); + this.appendValueInput('miso') + .setCheck(Number) + .appendField('MISO'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_INIT_TOOLTIP); + } +}; + +export const communicate_spi_set = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField("SPI") + this.appendValueInput('data') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_SERIAL_BEGIN); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_SET); + } +}; + +export const communicate_spi_buffer = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('SPI'); + this.appendValueInput('data') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_SET + Blockly.Msg.MIXLY_ESP32_SPI_BUFFER); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_BUFFER_SET); + } +}; + +export const communicate_spi_read = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('SPI'); + this.appendValueInput('data') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SERIAL_READ); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.LANG_MATH_BYTE) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_READ); + } +} + +export const communicate_spi_read_output = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('SPI'); + this.appendValueInput('data') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SERIAL_READ); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.LANG_MATH_BYTE + ' ' + Blockly.Msg.MIXLY_ESP32_SPI_OUTPUT); + this.appendValueInput('val') + .setCheck(Number); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_READ_OUTPUT); + } +} + +export const communicate_spi_readinto = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('SPI'); + this.appendValueInput('data') + .setCheck('var') + .appendField(Blockly.Msg.MIXLY_SERIAL_READ + Blockly.Msg.MIXLY_ESP32_SPI_BUFFER); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_READINTO); + } +} + +export const communicate_spi_readinto_output = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('SPI'); + this.appendValueInput('data') + .setCheck('var') + .appendField(Blockly.Msg.MIXLY_SERIAL_READ + Blockly.Msg.MIXLY_ESP32_SPI_BUFFER); + this.appendValueInput('val') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_SPI_OUTPUT); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_READINTO_OUTPUT); + } +} + +export const communicate_spi_write = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('SPI'); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_WRITE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_WRITE); + } +}; + +export const communicate_spi_write_readinto = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('SPI'); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_WRITE) + // .appendField(new Blockly.FieldDropdown([ + // [Blockly.Msg.LANG_MATH_BYTE, "byte"], + // [Blockly.Msg.MIXLY_ESP32_SPI_BUFFER, "buffer"] + // ]), "op"); + this.appendValueInput('val') + .setCheck('var') + .appendField(Blockly.Msg.MIXLY_ESP32_BUFFER_READ); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SPI_WRITE_READINTO); + } +}; + +export const communicate_i2c_master_read = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("I2C"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_READ); + this.setOutput(true, Number); + } +}; + +export const communicate_i2c_available = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("I2C"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_READ + Blockly.Msg.MIXLY_ESP32_SUCCESS); + this.setOutput(true, Boolean); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_I2C_AVAILABLE); + } +}; + +export const i2c_slave_onreceive = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_I2C_SLAVE_ONRECEIVE) + .setCheck(Number); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const communicate_ow_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('OneWire ' + Blockly.Msg.MIXLY_SETUP); + this.appendValueInput('BUS') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_PIN); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_OW_INIT); + } +}; + +export const communicate_ow_scan = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('OneWire'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_ONEWIRE_SCAN); + this.setOutput(true, 'List'); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_OW_SCAN); + } +}; + +export const communicate_ow_read = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('OneWire'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_ONEWIRE_READ); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_OW_READ); + } +}; + +export const communicate_ow_write = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('OneWire'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_WRITE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.LANG_MATH_STRING, "write"], + [Blockly.Msg.LANG_MATH_BYTE, "writebyte"] + ]), "op"); + this.appendValueInput('byte') + .setCheck([Number, String]); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_OW_WRITE); + } +}; + +export const communicate_ow_select = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .appendField('OneWire') + .setCheck('var') + this.appendValueInput('byte') + .setCheck(String) + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET) + .appendField("ROM"); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_OW_SELECT); + } +}; + + +export const communicate_ow_reset = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .appendField('OneWire') + .setCheck('var') + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_turtle_reset); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setOutput(false); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_OW_RESET); + } +}; + +export const communicate_ir_recv_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('PIN') + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_IR_RECEIVE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_TYPE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_IR_INPUT1, "8"], + [Blockly.Msg.MIXLY_IR_INPUT2, "16"], + [Blockly.Msg.MIXLY_IR_INPUT3, "0"], + [Blockly.Msg.MIXLY_TR_SEND_RC, "RC5"] + ]), "type"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO + Blockly.Msg.MIXLY_ESP32_ONENET_SUB); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const internal_variable = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXlY_RECV_FUN); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_IR_CMD_CODE, "0"], + [Blockly.Msg.MIXLY_IR_ADDR_CODE, "1"], + [Blockly.Msg.MIXLY_IR_RAW_CODE, "2"], + [Blockly.Msg.MIXLY_IR_PULSE, "3"] + ]), "index"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const recv_fun = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXlY_RECV_FUN) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MILY_PAUSE, "True"], + [Blockly.Msg.MIXLY_RECOVER, "False"] + ]), "en"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +} + +export const ir_whether_recv = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXlY_RECV_FUN); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IR_WHETHER_RECV); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const ir_recv_timeout = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('time') + .appendField(Blockly.Msg.MIXlY_RECV_FUN) + .appendField(Blockly.Msg.MIXLY_IR_TIMEOUT); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MILLISECOND); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const communicate_ir_send_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('PIN') + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_IR_SEND) + .appendField(Blockly.Msg.MIXLY_PIN); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_TYPE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_IR_SEND_samsung1, "False"], + [Blockly.Msg.MIXLY_IR_SEND_samsung2, "True"], + [Blockly.Msg.MIXLY_TR_SEND_RC, "RC5"] + ]), "type") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER); + this.appendValueInput('power'); + this.appendDummyInput() + .appendField(Blockly.Msg.MATH_QUYU_SYMBOL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + + +export const ir_transmit_conventional_data = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IR_SEND); + this.appendValueInput('cmd') + .appendField(Blockly.Msg.MIXLY_IR_CMD_CODE); + this.appendValueInput('addr') + .appendField(Blockly.Msg.MIXLY_IR_ADDR_CODE); + this.appendValueInput('toggle') + .appendField(Blockly.Msg.MIXLY_CONTROL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TRANSMIT_CONVEN_DATA); + } +}; + +export const ir_transmit_study_code = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IR_SEND); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_IR_PULSE) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const ir_transmit_raw_code = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IR_SEND); + this.appendValueInput('raw') + .appendField(Blockly.Msg.MIXLY_IR_RAW_CODE) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + + +export const ir_transmit_busy = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IR_TRANSMIT_DONE); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const communicate_bluetooth_central_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_BLUETOOTH) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MSG.catEthernet_init + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_AS + Blockly.Msg.MSG.catBLE_UART); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_WRITE); + } +} + +export const communicate_bluetooth_peripheral_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_BLUETOOTH) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MSG.catEthernet_init + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_AS + Blockly.Msg.MSG.catBLE_HID); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.HTML_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_WRITE); + } +} + +export const communicate_bluetooth_scan = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_ONEWIRE_SCAN + Blockly.Msg.MIXLY_BLUETOOTH); + this.setOutput(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_READ); + } +} + +export const communicate_bluetooth_mac = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_MAC); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const communicate_bluetooth_connect = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TEXT_JOIN + Blockly.Msg.MIXLY_BLUETOOTH) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.HTML_NAME, "name"], + [Blockly.Msg.MIXLY_ETHERNET_MAC_ADDRESS, "mac"] + ]), "mode"); + + this.appendValueInput('data') + .setCheck(String); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_WRITE); + } +} + +export const communicate_bluetooth_disconnect = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_DISCONNECT_ONENET); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const communicate_bluetooth_send = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_SEND_DATA); + this.appendValueInput('data') + .appendField(Blockly.Msg.HTML_BODY); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_WRITE); + } +} + +export const communicate_bluetooth_is_connected = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BLUETOOTH + Blockly.Msg.MIXLY_EMQX_IS_CONNECT); + this.setOutput(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_READ); + } +} + +export const communicate_bluetooth_recv = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendValueInput('METHOD') + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_RECV) + .appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO + Blockly.Msg.MIXLY_ESP32_ONENET_SUB); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + //this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_SUBSCRIBE_TOOLTIP); + } +}; + +export const communicate_bluetooth_recv_only = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_RECV) + this.setOutput(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_SUBSCRIBE_TOOLTIP); + } +}; + +export const communicate_bluetooth_handle = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField(Blockly.Msg.MIXLY_BLE_HANDLE) + this.appendValueInput('METHOD') + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_RECV) + .appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO + Blockly.Msg.MIXLY_ESP32_ONENET_SUB); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + //this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_SUBSCRIBE_TOOLTIP); + } +}; + +//espnow +export const communicate_espnow_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('ESPnow ' + Blockly.Msg.MIXLY_SETUP); + this.appendValueInput('CHNL') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_CHANNEL); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_TX_POWER) + .appendField(new Blockly.FieldDropdown([["20", "20"], ["18", "18"], ["16", "16"], ["15", "15"], ["14", "14"], ["13", "13"], ["11", "11"], ["8", "8"], ["7", "7"], ["5", "5"], ["2", "2"]]), 'op'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const communicate_espnow_init_new = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('ESPnow ' + Blockly.Msg.MIXLY_SETUP); + this.appendValueInput('CHNL') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_CHANNEL); + this.appendValueInput('DB') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER); + this.appendDummyInput() + .appendField('db'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MP_ESPNOW_INIT_TOOLTIP); + } +}; + +export const network_espnow_mac = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('ESPnow '); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_MAC); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const network_espnow_info = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('ESPnow '); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_INFO); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const network_espnow_recv = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('ESPnow '); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_RECV); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + ["(" + Blockly.Msg.MIXLY_ETHERNET_MAC_ADDRESS + ", " + Blockly.Msg.OLED_STRING + ")", ""], + [Blockly.Msg.MIXLY_ETHERNET_MAC_ADDRESS, "[0]"], + [Blockly.Msg.OLED_STRING, "[1]"] + ]), "mode"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const network_espnow_send = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('ESPnow '); + this.appendValueInput('mac') + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_SEND_MAC); + this.appendValueInput('content') + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_SEND); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXGO_ESPNOW_SEND_TOOLTIP); + } +}; + +export const network_espnow_recv_handle = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('ESPnow '); + this.appendValueInput('METHOD') + .appendField(Blockly.Msg.MIXLY_EMQX_SET_METHOD); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +//radio +export const espnow_radio_channel = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_INIT); + this.appendValueInput('CHNL') + .setCheck(Number); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const espnow_radio_txpower = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_MP_ESPNOW_RADIO + Blockly.Msg.MIXLY_TX_POWER) + .appendField(new Blockly.FieldDropdown([["20", "20"], ["18", "18"], ["16", "16"], ["15", "15"], ["14", "14"], ["13", "13"], ["11", "11"], ["8", "8"], ["7", "7"], ["5", "5"], ["2", "2"]]), 'op'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const espnow_radio_channel_new = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_INIT); + this.appendValueInput('CHNL') + .setCheck(Number); + this.appendValueInput('DB') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_BLE_POWER); + this.appendDummyInput() + .appendField('db'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_INIT_TOOLTIP); + } +}; + +export const espnow_radio_on_off = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_ON, "True"], + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_OFF, "False"] + ]), 'on_off') + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const espnow_radio_send = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_SEND); + this.appendValueInput('send') + .setCheck(String); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXGO_ESPNOW_SEND_TOOLTIP); + } +}; + +export const espnow_radio_rec = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO) + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_RECV); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const espnow_radio_recv_msg = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_RECEIVED_MSG); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const espnow_radio_recv = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_MSG_RECEIVED); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(false); + this.setNextStatement(false); + } +}; + +export const espnow_radio_recv_certain_msg = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_MSG_RECEIVED_CERTAIN) + .appendField('"') + .appendField(new Blockly.FieldTextInput('on'), 'msg') + .appendField('"') + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(false); + this.setNextStatement(false); + } +}; + +export const espnow_radio_recv_new = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_MSG_RECEIVED); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(false); + this.setNextStatement(false); + } +}; + +export const espnow_radio_recv_certain_msg_new = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MP_ESPNOW_RADIO_MSG_RECEIVED_CERTAIN) + .appendField('"') + .appendField(new Blockly.FieldTextInput('on'), 'msg') + .appendField('"') + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(false); + this.setNextStatement(false); + } +}; + +export const lora_init = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('SUB') + .appendField('Lora' + Blockly.Msg.MIXLY_SETUP) + .setCheck("var"); + this.appendValueInput('SPISUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "SPI") + .setCheck("var"); + this.appendValueInput('PINSUB') + .appendField("CS") + this.appendValueInput('frequency') + .appendField(Blockly.Msg.MIXLY_FREQUENCY) + this.appendValueInput('rate') + .appendField(Blockly.Msg.MIXLY_CODE_RATE) + this.appendValueInput('factor') + .appendField(Blockly.Msg.MIXLY_SPREADING_FACTOR) + this.appendValueInput('power') + .appendField(Blockly.Msg.MIXLY_TX_POWER) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SIGNAL_BANDWIDTH) + .appendField(new Blockly.FieldDropdown([ + ['7800', '7800'], + ['10400', '10400'], + ['15600', '15600'], + ['20800', '20800'], + ['31250', '31250'], + ['41700', '41700'], + ['62500', '62500'], + ['125000', '125000'], + ['250000', '250000'], + ['500000', '500000'] + ]), 'bandwidth') + this.setFieldValue("125000", "bandwidth"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_LORA_INIT_TOOLTIP); + } +}; + +export const lora_packet = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('Lora '); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_PACKAGE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SIGNAL_STRENGTH, 'packet_rssi'], + [Blockly.Msg.MIXLY_SIGNAL_NOISE_RATE, 'packet_snr'] + ]), 'key') + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const lora_send = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField('Lora '); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SEND_DATA); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_SEND); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + //this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_I2C_WRITE); + } +} + +export const lora_recv = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('VAR') + .setCheck('var') + .appendField('Lora '); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_RECV) + this.setOutput(true, String); + this.setInputsInline(true); + } +}; + +export const urequests_get = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput("DOMAIN") + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .setCheck(String); + this.appendDummyInput("") + + .appendField(Blockly.Msg.blockpy_REQUESTS_GET) + .appendField(new Blockly.FieldTextInput('response'), 'VAR') + + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.blockpy_REQUESTS_GET_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } + +} + + +export const urequests_attribute = { + init: function () { + this.appendValueInput('VAL') + + var attr = + [[Blockly.Msg.blockpy_REQUESTS_GET_ATTR_HEADER, 'headers'], [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_STATUS_CODE, 'status_code'], [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_TEXT, 'text'] + , [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_COOKIES, 'cookies'], [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_CONTENT, 'content']]; + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown(attr), 'ATTR') + + + this.setInputsInline(true); + this.setOutput(true, String); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('DIR'); + var TOOLTIPS = { + 'clear': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_CLEAR, + 'reset': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_RESET, + 'home': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_HOME + }; + return TOOLTIPS[mode]; + }); + } +}; + + + +export const urequests_method = { + init: function () { + this.appendValueInput("VAR") + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .setCheck(String); + var method = [ + ['get', 'get'], + ['post', 'post'], + ['put', 'put'], + ['delete', 'delete'], + ['head', 'head'], + ['option', 'option'] + ]; + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_CONDUCT) + .appendField(new Blockly.FieldDropdown(method), 'DIR') + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_REQUESTS) + this.setOutput(true); + this.setInputsInline(true); + + } +}; + +export const i2c_init = communicate_i2c_init; +export const i2c_read = communicate_i2c_read; +export const i2c_write = communicate_i2c_write; +export const i2c_scan = communicate_i2c_scan; +export const spi_init = communicate_spi_init; +export const spi_set = communicate_spi_set; +export const spi_buffer = communicate_spi_buffer; +export const spi_read = communicate_spi_read; +export const spi_read_output = communicate_spi_read_output; +export const spi_readinto = communicate_spi_readinto; +export const spi_readinto_output = communicate_spi_readinto_output; +export const spi_write = communicate_spi_write; +export const spi_write_readinto = communicate_spi_write_readinto; +export const i2c_master_reader2 = communicate_i2c_master_read; +export const i2c_available = communicate_i2c_available; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/control.js b/mixly/boards/default_src/micropython/blocks/control.js new file mode 100644 index 00000000..c9294778 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/control.js @@ -0,0 +1,623 @@ +import * as Blockly from 'blockly/core'; + +const LOOPS_HUE = 120//'#EB8045'; + +export const base_setup = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP); + this.appendStatementInput('DO') + .appendField(''); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_SETUP); + } +}; + +export const controls_delay = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DELAY) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SECOND, "s"], + [Blockly.Msg.MIXLY_mSecond, "ms"], + [Blockly.Msg.MIXLY_uSecond, "us"] + ]), 'Time'); + this.appendValueInput("DELAY_TIME", Number) + .setCheck(Number); + this.setFieldValue('ms', 'Time') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_DELAY); + } +}; + +export const Panic_with_status_code = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput("STATUS_CODE", Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_Panic_with_status_code) + .setCheck(Number); + this.setPreviousStatement(true, null); + // this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Panic_with_status_code); + } +}; + +export const reset = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_micro); + this.setPreviousStatement(true); + // this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Reset_micro); + } +}; + +export const controls_for = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_WITH) + .appendField(new Blockly.FieldTextInput('i'), 'VAR'); + this.appendValueInput('FROM') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_FROM); + this.appendValueInput('TO') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_TO); + this.appendValueInput('STEP') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEP); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1', + thisBlock.getFieldValue('VAR')); + }); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const controls_whileUntil = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput('BOOL') + .setCheck([Boolean, Number]) + .appendField(Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_TITLE_REPEAT) + .appendField(new Blockly.FieldDropdown(controls_whileUntil.OPERATORS), 'MODE'); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('MODE'); + var TOOLTIPS = { + 'WHILE': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE, + 'UNTIL': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL + }; + return TOOLTIPS[op]; + }); + }, + OPERATORS: [ + [Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'], + [Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, 'UNTIL'] + ] +}; + +export const controls_flow_statements = { + init: function () { + this.setColour(LOOPS_HUE); + var dropdown = new Blockly.FieldDropdown(controls_flow_statements.OPERATORS); + this.appendDummyInput() + .appendField(dropdown, 'FLOW') + .appendField(Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_INPUT_OFLOOP); + this.setPreviousStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('FLOW'); + var TOOLTIPS = { + 'BREAK': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK, + 'CONTINUE': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE + }; + return TOOLTIPS[op]; + }); + }, + onchange: function () { + if (!this.workspace) { + // Block has been deleted. + return; + } + var legal = false; + // Is the block nested in a control statement? + var block = this; + do { + if (block.type == 'controls_repeat' || + block.type == 'controls_for' || + block.type == 'controls_forEach' || + block.type == 'controls_repeat_ext' || + block.type == 'controls_whileUntil') { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + OPERATORS: [ + [Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'], + [Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE, 'CONTINUE'] + ] +}; + +export const controls_millis = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RUNTIME); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_mSecond, "ms"], [Blockly.Msg.MIXLY_uSecond, "us"]]), 'Time'); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_RUNTIME); + } +}; + +export const controls_if = { + /** + * Block for if/elseif/else condition. + * @this Blockly.Block + */ + init: function () { + //this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL); + this.setColour(LOOPS_HUE); + this.appendValueInput('IF0') + .setCheck([Boolean, Number]) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendStatementInput('DO0') + .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setHelpUrl("https://mixly.readthedocs.io/zh_CN/latest/arduino/03.Control.html#if"); + this.setMutator(new Blockly.icons.MutatorIcon(['controls_if_elseif', + 'controls_if_else'], this)); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + if (!thisBlock.elseifCount_ && !thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_1; + } else if (!thisBlock.elseifCount_ && thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_2; + } else if (thisBlock.elseifCount_ && !thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_3; + } else if (thisBlock.elseifCount_ && thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_4; + } + return ''; + }); + this.elseifCount_ = 0; + this.elseCount_ = 0; + }, + /** + * Create XML to represent the number of else-if and else inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + if (!this.elseifCount_ && !this.elseCount_) { + return null; + } + var container = document.createElement('mutation'); + if (this.elseifCount_) { + container.setAttribute('elseif', this.elseifCount_); + } + if (this.elseCount_) { + container.setAttribute('else', 1); + } + return container; + }, + /** + * Parse XML to restore the else-if and else inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var containerBlock = this; + var valueConnections = []; + var statementConnections = []; + // var elseStatementConnection = null; + if (this.elseCount_) { + // if (containerBlock.getInputTargetBlock('ELSE') && containerBlock.getInputTargetBlock('ELSE').previousConnection) + // elseStatementConnection = containerBlock.getInputTargetBlock('ELSE').previousConnection; + this.removeInput('ELSE'); + } + for (var i = this.elseifCount_; i > 0; i--) { + if (containerBlock.getInputTargetBlock('IF' + i) && containerBlock.getInputTargetBlock('IF' + i).previousConnection) + valueConnections[i] = (containerBlock.getInputTargetBlock('IF' + i).previousConnection); + else + valueConnections[i] = null; + this.removeInput('IF' + i); + if (containerBlock.getInputTargetBlock('DO' + i) && containerBlock.getInputTargetBlock('DO' + i).previousConnection) + statementConnections[i] = (containerBlock.getInputTargetBlock('DO' + i).previousConnection); + else + statementConnections[i] = null; + this.removeInput('DO' + i); + } + this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10); + this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10); + //this.compose(containerBlock); + for (var i = 1; i <= this.elseifCount_; i++) { + this.appendValueInput('IF' + i) + .setCheck([Boolean, Number]) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF); + this.appendStatementInput('DO' + i) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN); + } + if (this.elseCount_) { + this.appendStatementInput('ELSE') + .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE); + } + for (var i = valueConnections.length - 2; i > 0; i--) { + if (valueConnections[i]) + valueConnections[i].reconnect(this, 'IF' + i); + } + for (var i = statementConnections.length - 2; i > 0; i--) { + if (statementConnections[i]) + statementConnections[i].reconnect(this, 'DO' + i); + } + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = workspace.newBlock('controls_if_if'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 1; i <= this.elseifCount_; i++) { + var elseifBlock = workspace.newBlock('controls_if_elseif'); + elseifBlock.initSvg(); + connection.connect(elseifBlock.previousConnection); + connection = elseifBlock.nextConnection; + } + if (this.elseCount_) { + var elseBlock = workspace.newBlock('controls_if_else'); + elseBlock.initSvg(); + connection.connect(elseBlock.previousConnection); + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + // Disconnect the else input blocks and remove the inputs. + if (this.elseCount_) { + this.removeInput('ELSE'); + } + this.elseCount_ = 0; + // Disconnect all the elseif input blocks and remove the inputs. + for (var i = this.elseifCount_; i > 0; i--) { + this.removeInput('IF' + i); + this.removeInput('DO' + i); + } + this.elseifCount_ = 0; + // Rebuild the block's optional inputs. + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + var valueConnections = [null]; + var statementConnections = [null]; + var elseStatementConnection = null; + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_if_elseif': + this.elseifCount_++; + valueConnections.push(clauseBlock.valueConnection_); + statementConnections.push(clauseBlock.statementConnection_); + break; + case 'controls_if_else': + this.elseCount_++; + elseStatementConnection = clauseBlock.statementConnection_; + break; + default: + throw Error('Unknown block type: ' + clauseBlock.type); + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + + this.updateShape_(); + // Reconnect any child blocks. + this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); + + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 1; + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_if_elseif': + var inputIf = this.getInput('IF' + i); + var inputDo = this.getInput('DO' + i); + clauseBlock.valueConnection_ = + inputIf && inputIf.connection.targetConnection; + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + i++; + break; + case 'controls_if_else': + var inputDo = this.getInput('ELSE'); + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + break; + default: + throw 'Unknown block type.'; + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + }, + /** + * Reconstructs the block with all child blocks attached. + */ + rebuildShape_: function () { + var valueConnections = [null]; + var statementConnections = [null]; + var elseStatementConnection = null; + + if (this.getInput('ELSE')) { + elseStatementConnection = this.getInput('ELSE').connection.targetConnection; + } + var i = 1; + while (this.getInput('IF' + i)) { + var inputIf = this.getInput('IF' + i); + var inputDo = this.getInput('DO' + i); + console.log(inputIf.connection.targetConnection); + valueConnections.push(inputIf.connection.targetConnection); + statementConnections.push(inputDo.connection.targetConnection); + i++; + } + this.updateShape_(); + this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); + }, + /** + * Modify this block to have the correct number of inputs. + * @this Blockly.Block + * @private + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('ELSE')) { + this.removeInput('ELSE'); + } + var i = 1; + while (this.getInput('IF' + i)) { + this.removeInput('IF' + i); + this.removeInput('DO' + i); + i++; + } + // Rebuild block. + for (var i = 1; i <= this.elseifCount_; i++) { + this.appendValueInput('IF' + i) + .setCheck([Number, Boolean]) + .appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSEIF']); + this.appendStatementInput('DO' + i) + .appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']); + } + if (this.elseCount_) { + this.appendStatementInput('ELSE') + .appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSE']); + } + }, + /** + * Reconnects child blocks. + * @param {!Array} valueConnections List of value + * connectsions for if input. + * @param {!Array} statementConnections List of + * statement connections for do input. + * @param {?Blockly.RenderedConnection} elseStatementConnection Statement + * connection for else input. + */ + reconnectChildBlocks_: function (valueConnections, statementConnections, + elseStatementConnection) { + for (var i = 1; i <= this.elseifCount_; i++) { + valueConnections[i] && Blockly.Mutator.reconnect(this, 'IF' + i); + statementConnections[i] && statementConnections[i].reconnect(this, 'DO' + i); + } + elseStatementConnection && elseStatementConnection.reconnect(this, 'ELSE'); + } +}; + +export const controls_if_if = { + /** + * Mutator block for if container. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP); + this.contextMenu = false; + } +}; + +export const controls_if_elseif = { + /** + * Mutator bolck for else-if condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP); + this.contextMenu = false; + } +}; + +export const controls_if_else = { + /** + * Mutator block for else condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP); + this.contextMenu = false; + } +}; + + +export const controls_end_program = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CONTROL_END_PROGRAM); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_CONTROL_END_PROGRAM); + } +}; + + +export const controls_forEach = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput('LIST') + .setCheck(['List', String]) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM) + .appendField(new Blockly.FieldTextInput('i'), 'VAR'); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1', + thisBlock.getFieldValue('VAR')); + }); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const raw_block = { + // Container. + init: function () { + this.setColour(LOOPS_HUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendDummyInput() + .appendField('Code Block:'); + this.appendDummyInput() + .appendField(new Blockly.FieldMultilineInput('12345'), 'TEXT'); + } +}; + +export const base_type = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput("DATA") + .appendField(Blockly.Msg.MICROBIT_PYTHON_TYPE); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MICROBIT_PYTHON_TYPE); + } +}; + +export const controls_TypeLists = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_GET_TYPE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.LANG_MATH_INT, "int"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_FLOAT, "float"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING, "str"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, "list"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, "tuple"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, "dict"], + [Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, "set"], + // [Blockly.Msg.MIXLY_MICROBIT_IMAGE,"image"], + [Blockly.Msg.LOGIC_NULL, "NoneType"]]), "type"); + //整数、浮点数、字符串、列表、元组、字典、集合、图像不太对, unfinished + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('type'); + var mode0 = Blockly.Msg.MICROBIT_controls_TypeLists; + var TOOLTIPS = { + 'int': Blockly.Msg.LANG_MATH_INT, + 'float': Blockly.Msg.MIXLY_MICROBIT_TYPE_FLOAT, + 'str': Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING, + 'list': Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, + 'tuple': Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, + 'dict': Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, + 'set': Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, + 'image': Blockly.Msg.MIXLY_MICROBIT_IMAGE, + 'NoneType': Blockly.Msg.LOGIC_NULL + }; + return mode0 + TOOLTIPS[mode]; + }); + } +}; + +export const controls_uname = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_UNAME); + + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_UNAME); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/display.js b/mixly/boards/default_src/micropython/blocks/display.js new file mode 100644 index 00000000..84e992b2 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/display.js @@ -0,0 +1,1955 @@ +import * as Blockly from 'blockly/core'; + +const DISPLAY_HUE = 180; + +const FIELD_COLOUR_CONFIG = { + colourOptions: ['#f00', '#000'], + columns: 2 +}; + +//var IMG = [["HEART", "HEART"],["HEART_SMALL", "HEART_SMALL"],["HAPPY", "HAPPY"],["SAD", "SAD"],["SMILE", "SMILE"],["SILLY", "SILLY"],["FABULOUS", "FABULOUS"],["SURPRISED", "SURPRISED"],["ASLEEP", "ASLEEP"],["ANGRY", "ANGRY"],["CONFUSED", "CONFUSED"],["NO", "NO"],["YES", "YES"],["LEFT_ARROW", "LEFT_ARROW"],["RIGHT_ARROW", "RIGHT_ARROW"],["DRESS", "DRESS"],["TRANSFORMERS", "TRANSFORMERS"],["SCISSORS", "SCISSORS"],["EXIT", "EXIT"],["TREE", "TREE"],["PACMAN", "PACMAN"],["TARGET", "TARGET"],["TSHIRT", "TSHIRT"],["ROLLERSKATE", "ROLLERSKATE"],["DUCK", "DUCK"],["HOUSE", "HOUSE"],["TORTOISE", "TORTOISE"],["BUTTERFLY", "BUTTERFLY"],["STICKFIGURE", "STICKFIGURE"],["GHOST", "GHOST"],["PITCHFORK", "PITCHFORK"],["MUSIC_QUAVERS", "MUSIC_QUAVERS"],["MUSIC_QUAVER", "MUSIC_QUAVER"],["MUSIC_CROTCHET", "MUSIC_CROTCHET"],["COW", "COW"],["RABBIT", "RABBIT"],["SQUARE_SMALL", "SQUARE_SMALL"],["SQUARE", "SQUARE"],["DIAMOND_SMALL", "DIAMOND_SMALL"],["DIAMOND", "DIAMOND"],["CHESSBOARD", "CHESSBOARD"],["TRIANGLE_LEFT", "TRIANGLE_LEFT"],["TRIANGLE", "TRIANGLE"],["SNAKE", "SNAKE"],["UMBRELLA", "UMBRELLA"],["SKULL", "SKULL"],["GIRAFFE", "GIRAFFE"],["SWORD", "SWORD"]]; + +export const display_clear = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "nextStatement": null, + "previousStatement": null, + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.clear", + "message0": Blockly.Msg.MIXLY_MICROBIT_Clear_display + }); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + } +}; + +export const display_get_pixel = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_POINT); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_BRIGHTNESS); + } +}; + +export const display_bright_point = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BRIGHTNESS) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendValueInput("STAT") + .setCheck([Number, Boolean]); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_DISPLAY_SETPIXEL); + } +}; + +export const monitor_show_string = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('data') + .setCheck(String) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.OLED_DRAWSTR_ONE_BY_ONE, 'show'], + [Blockly.Msg.MIXLY_ESP32_MONITOR_SCROLL, 'scroll'] + ]), "MODE") + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.OLED_DRAWSTR; + var TOOLTIPS = { + 'show': Blockly.Msg.OLED_DRAWSTR_ONE_BY_ONE, + 'scroll': Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING + }; + return TOOLTIPS[mode] + mode0; + }); + } +}; + +export const monitor_show_scroll_string = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('data') + .setCheck(String) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.OLED_DRAWSTR_ONE_BY_ONE, 'show'], + [Blockly.Msg.MIXLY_ESP32_MONITOR_SCROLL, 'scroll'] + ]), "MODE") + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("time") + .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DELAY); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.OLED_DRAWSTR; + var TOOLTIPS = { + 'show': Blockly.Msg.OLED_DRAWSTR_ONE_BY_ONE, + 'scroll': Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING + }; + return TOOLTIPS[mode] + mode0; + }); + } +}; + +export const display_show_static = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_STATIC); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MUSIC_SHOW_STATIC); + } +}; + +export const microbit_display_show_image = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('PIN', String) + .setCheck("esp32_image") + .appendField(Blockly.Msg.OLED_BITMAP); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP); + } +}; + +export const esp32_display_show_default_image = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "InputsInline": true, + "nextStatement": null, + "previousStatement": null, + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.show", + "tooltip": "Show the referenced image on the display.", + "message0": Blockly.Msg.OLED_BITMAP, + "args0": [ + { + "name": "image", + "options": [ + ["HEART", "HEART"], + ["HEART_SMALL", "HEART_SMALL"], + ["HAPPY", "HAPPY"], + ["SAD", "SAD"], + ["SMILE", "SMILE"], + ["SILLY", "SILLY"], + ["FABULOUS", "FABULOUS"], + ["SURPRISED", "SURPRISED"], + ["ASLEEP", "ASLEEP"], + ["ANGRY", "ANGRY"], + ["CONFUSED", "CONFUSED"], + ["NO", "NO"], + ["YES", "YES"], + ["LEFT_ARROW", "LEFT_ARROW"], + ["RIGHT_ARROW", "RIGHT_ARROW"], + ["DRESS", "DRESS"], + ["TRANSFORMERS", "TRANSFORMERS"], + ["SCISSORS", "SCISSORS"], + ["EXIT", "EXIT"], + ["TREE", "TREE"], + ["PACMAN", "PACMAN"], + ["TARGET", "TARGET"], + ["TSHIRT", "TSHIRT"], + ["ROLLERSKATE", "ROLLERSKATE"], + ["DUCK", "DUCK"], + ["HOUSE", "HOUSE"], + ["TORTOISE", "TORTOISE"], + ["BUTTERFLY", "BUTTERFLY"], + ["STICKFIGURE", "STICKFIGURE"], + ["GHOST", "GHOST"], + ["PITCHFORK", "PITCHFORK"], + ["MUSIC_QUAVERS", "MUSIC_QUAVERS"], + ["MUSIC_QUAVER", "MUSIC_QUAVER"], + ["MUSIC_CROTCHET", "MUSIC_CROTCHET"], + ["COW", "COW"], + ["RABBIT", "RABBIT"], + ["SQUARE_SMALL", "SQUARE_SMALL"], + ["SQUARE", "SQUARE"], + ["DIAMOND_SMALL", "DIAMOND_SMALL"], + ["DIAMOND", "DIAMOND"], + ["CHESSBOARD", "CHESSBOARD"], + ["TRIANGLE_LEFT", "TRIANGLE_LEFT"], + ["TRIANGLE", "TRIANGLE"], + ["SNAKE", "SNAKE"], + ["UMBRELLA", "UMBRELLA"], + ["SKULL", "SKULL"], + ["GIRAFFE", "GIRAFFE"], + ["SWORD", "SWORD"] + ], + "type": "field_dropdown" + } + ] + }); + } +}; + +export const esp32_display_show_animation = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.show", + "message0": Blockly.Msg.MIXLY_MICROBIT_Animate_images, + "args0": [ + { + "check": "List", + "type": "input_value", + "name": "images" + }, { + "type": "input_value", + "name": "delay" + }, { + "type": "input_dummy" + }, { + "checked": true, + "type": "field_checkbox", + "name": "wait" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "loop" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "clear" + } + ] + }); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SHOW_delay + Blockly.Msg.MIXLY_MICROBIT_Animate_images1); + } +}; + +export const esp32_display_scroll = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "nextStatement": null, + "previousStatement": null, + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.scroll", + "tooltip": "Scroll the referenced text across the display.", + "message0": Blockly.Msg.MIXLY_MICROBIT_Scroll_message, + "args0": [{ + "check": "String", + "type": "input_value", + "name": "message" + } + ] + }); + } +}; + +export const esp32_display_on = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_Turn_on_display, 'on'], + [Blockly.Msg.MIXLY_MICROBIT_Turn_off_display, 'off'] + ]), 'on_off') + .appendField(Blockly.Msg.MIXLY_MICROBIT_monitor); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('on_off'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_monitor; + var TOOLTIPS = { + 'on': Blockly.Msg.MIXLY_MICROBIT_Turn_on_display, + 'off': Blockly.Msg.MIXLY_MICROBIT_Turn_off_display + }; + return TOOLTIPS[mode] + mode0; + }); + } +}; + +export const esp32_display_off = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "nextStatement": null, + "previousStatement": null, + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.off", + "tooltip": "Turn off the display.", + "message0": Blockly.Msg.MIXLY_MICROBIT_Turn_off_display + }); + } +}; + +export const esp32_display_is_on = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "output": "Boolean", + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.is_on", + "message0": Blockly.Msg.MIXLY_MICROBIT_Display_is_on + }); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Display_is_on1); + } +}; + +export const display_image_builtins = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "args0": [{ + "name": "image", + "options": [ + ["HEART", "HEART"], + ["HEART_SMALL", "HEART_SMALL"], + ["HAPPY", "HAPPY"], + ["SAD", "SAD"], + ["SMILE", "SMILE"], + ["SILLY", "SILLY"], + ["FABULOUS", "FABULOUS"], + ["SURPRISED", "SURPRISED"], + ["ASLEEP", "ASLEEP"], + ["ANGRY", "ANGRY"], + ["CONFUSED", "CONFUSED"], + ["NO", "NO"], + ["YES", "YES"], + ["LEFT_ARROW", "LEFT_ARROW"], + ["RIGHT_ARROW", "RIGHT_ARROW"], + ["DRESS", "DRESS"], + ["TRANSFORMERS", "TRANSFORMERS"], + ["SCISSORS", "SCISSORS"], + ["EXIT", "EXIT"], + ["TREE", "TREE"], + ["PACMAN", "PACMAN"], + ["TARGET", "TARGET"], + ["TSHIRT", "TSHIRT"], + ["ROLLERSKATE", "ROLLERSKATE"], + ["DUCK", "DUCK"], + ["HOUSE", "HOUSE"], + ["TORTOISE", "TORTOISE"], + ["BUTTERFLY", "BUTTERFLY"], + ["STICKFIGURE", "STICKFIGURE"], + ["GHOST", "GHOST"], + ["PITCHFORK", "PITCHFORK"], + ["MUSIC_QUAVERS", "MUSIC_QUAVERS"], + ["MUSIC_QUAVER", "MUSIC_QUAVER"], + ["MUSIC_CROTCHET", "MUSIC_CROTCHET"], + ["COW", "COW"], + ["RABBIT", "RABBIT"], + ["SQUARE_SMALL", "SQUARE_SMALL"], + ["SQUARE", "SQUARE"], + ["DIAMOND_SMALL", "DIAMOND_SMALL"], + ["DIAMOND", "DIAMOND"], + ["CHESSBOARD", "CHESSBOARD"], + ["TRIANGLE_LEFT", "TRIANGLE_LEFT"], + ["TRIANGLE", "TRIANGLE"], + ["SNAKE", "SNAKE"], + ["UMBRELLA", "UMBRELLA"], + ["SKULL", "SKULL"], + ["GIRAFFE", "GIRAFFE"], + ["SWORD", "SWORD"] + ], + "type": "field_dropdown" + } + ], + "output": ["esp32_image", "List"], + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/image.html#attributes", + "tooltip": Blockly.Msg.MIXLY_MICROBIT_Built_in_image1, + "message0": Blockly.Msg.MIXLY_MICROBIT_Built_in_image + }); + } +}; + +export const display_image_create = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_HUE, + "args0": [ + { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "00" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "01" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "02" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "03" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "04" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "05" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "06" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "07" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "08" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "09" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "0a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "0b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "0c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "0d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "0e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "0f" + }, { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "10" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "11" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "12" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "13" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "14" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "15" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "16" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "17" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "18" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "19" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "1a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "1b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "1c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "1d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "1e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "1f" + }, { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "20" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "21" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "22" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "23" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "24" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "25" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "26" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "27" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "28" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "29" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "2a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "2b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "2c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "2d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "2e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "2f" + }, { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "30" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "31" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "32" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "33" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "34" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "35" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "36" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "37" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "38" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "39" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "3a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "3b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "3c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "3d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "3e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "3f" + }, { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "40" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "41" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "42" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "43" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "44" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "45" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "46" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "47" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "48" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "49" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "4a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "4b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "4c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "4d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "4e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "4f" + }, { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "50" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "51" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "52" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "53" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "54" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "55" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "56" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "57" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "58" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "59" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "5a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "5b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "5c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "5d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "5e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "5f" + }, { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "60" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "61" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "62" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "63" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "64" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "65" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "66" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "67" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "68" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "69" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "6a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "6b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "6c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "6d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "6e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "6f" + }, { + "type": "input_dummy" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "70" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "71" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "72" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "73" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "74" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "75" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "76" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "77" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "78" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "79" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "7a" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "7b" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "7c" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "7d" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "7e" + }, { + "colour": "#000000", + "type": "field_colour", + "name": "7f" + } + ], + "output": "esp32_image", + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/image.html#microbit.Image", + "message0": Blockly.Msg.MIXLY_ESP32_Create_image + }); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + } +}; + +export const image_shift = { + init: function () { + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(DISPLAY_HUE); + this.setOutput(true); + this.setInputsInline(true); + this.appendValueInput('img') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET) + .setCheck(["esp32_image", "List", String]); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .appendField(new Blockly.FieldDropdown(image_shift.OPERATORS), 'OP'); + this.appendValueInput('val') + .appendField(Blockly.Msg.DISPLAY_IMAGE_SHIFT) + .setCheck(Number); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_UNIT) + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var mode0 = Blockly.Msg.DISPLAY_IMAGE_LET; + var mode1 = Blockly.Msg.DISPLAY_IMAGE_LET2; + var mode2 = Blockly.Msg.DISPLAY_IMAGE_LET3; + var TOOLTIPS = { + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT + }; + return mode0 + mode1 + TOOLTIPS[mode] + mode2; + }); + }, + OPERATORS: [ + [Blockly.Msg.MIXLY_UP, 'up'], + [Blockly.Msg.MIXLY_DOWN, 'down'], + [Blockly.Msg.MIXLY_LEFT, 'left'], + [Blockly.Msg.MIXLY_RIGHT, 'right'], + ] +}; + +export const image_arithmetic = { + init: function () { + //this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL); + this.setColour(DISPLAY_HUE); + this.setOutput(true, "esp32_image"); + this.appendValueInput('A') + // .setCheck(["esp32_image", "List", String]) + .appendField(Blockly.Msg.MICROBIT_DISPLAY_MERGE_SHAPE); + this.appendValueInput('B') + // .setCheck(["esp32_image", "List", String]) + .appendField(new Blockly.FieldDropdown(image_arithmetic.OPERATORS), 'OP'); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + '+': Blockly.Msg.MIXLY_MICROBIT_image_add, + '-': Blockly.Msg.MIXLY_MICROBIT_image_reduce + }; + return TOOLTIPS[mode]; + }); + }, + OPERATORS: [ + [Blockly.Msg.MICROBIT_DISPLAY_UNION, '+'], + [Blockly.Msg.MICROBIT_DISPLAY_MINUS, '-'] + ] +}; + +export const esp32_display_show_string = { + init: function () { + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.OLED_DRAWSTR_ONE_BY_ONE, 'show'], + [Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING, 'scroll'] + ]), "MODE"); + this.jsonInit({ + "colour": DISPLAY_HUE, + "inputsInline": true, + "nextStatement": null, + "previousStatement": null, + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.show", + "tooltip": "Display the list of images as an animation with a certain delay between each frame. Indicate if you need to wait before continuing, continuously loop the animation and clear the display when finished.", + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_STRING, + "args0": [{ + "check": String, + "type": "input_value", + "name": "images" + }, { + "type": "input_value", + "name": "delay" + }, { + "type": "input_dummy" + }, { + "checked": true, + "type": "field_checkbox", + "name": "wait" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "loop" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "clear" + } + ] + }); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.OLED_DRAWSTR; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SHOW_delay; + var TOOLTIPS = { + 'show': Blockly.Msg.OLED_DRAWSTR_ONE_BY_ONE, + 'scroll': Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING + }; + return mode1 + TOOLTIPS[mode] + mode0; + }); + } +}; + +// export const esp32_display_scroll_string = { +// init : function () { +// this.jsonInit({ +// "colour" : DISPLAY_HUE, +// "inputsInline": true, +// "nextStatement" : null, +// "previousStatement" : null, +// "helpUrl" : "https://microbit-micropython.readthedocs.io/en/latest/display.html#microbit.display.show", +// "tooltip" : "Display the list of images as an animation with a certain delay between each frame. Indicate if you need to wait before continuing, continuously loop the animation and clear the display when finished.", +// "message0" : Blockly.Msg.MIXLY_MICROBIT_Scroll_string, +// "args0" : [{ +// "check" : String, +// "type" : "input_value", +// "name" : "images" +// }, { +// "type" : "input_value", +// "name" : "delay" +// }, { +// "type" : "input_dummy" +// }, { +// "checked" : true, +// "type" : "field_checkbox", +// "name" : "wait" +// }, { +// "type" : "input_dummy" +// }, { +// "checked" : false, +// "type" : "field_checkbox", +// "name" : "loop" +// }, { +// "type" : "input_dummy" +// }, { +// "checked" : false, +// "type" : "field_checkbox", +// "name" : "clear" +// } +// ] +// }); +// } +// }; + +export const group_lcd_print = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput("TEXT", String) + .setCheck([String, Number]) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DF_LCD) + .appendField('mylcd') + //.appendField(new Blockly.FieldTextInput('mylcd'), 'VAR') + .appendField(Blockly.Msg.MIXLY_LCD_PRINT1); + this.appendValueInput("TEXT2", String) + .setCheck([String, Number]) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_LCD_PRINT2); + /* + this.appendValueInput("TEXT3", String) + .setCheck([String,Number]) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_LCD_PRINT3); + this.appendValueInput("TEXT4", String) + .setCheck([String,Number]) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_LCD_PRINT4); + */ + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_LCD_PRINT4_TOOLTIP); + } +}; + +export const group_lcd_init = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('device') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(Blockly.Msg.MIXLY_DF_LCD) + .appendField('1602') + .appendField('mylcd') + .appendField(Blockly.Msg.MIXLY_LCD_ADDRESS); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_DF_LCD + Blockly.Msg.MIXLY_LCD_ADDRESS); + } +}; + +export const group_lcd_print2 = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput("row", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DF_LCD) + .appendField('mylcd') + .appendField(Blockly.Msg.MIXLY_LCD_ROW); + this.appendValueInput("column", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_LCD_COLUMN); + this.appendValueInput("TEXT", String) + .setCheck([String, Number]) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_LCD_PRINT); + this.setPreviousStatement(true, null); + this.setInputsInline(true); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_LCD_PRINT3_TOOLTIP); + } +}; + +export const group_lcd_power = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DF_LCD) + .appendField('mylcd') + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ON, "on()"], + [Blockly.Msg.MIXLY_OFF, "off()"], + [Blockly.Msg.MIXLY_LCD_STAT_CLEAR, "clear()"], + [Blockly.Msg.MIXLY_LCD_NOBACKLIGHT, "backlight(off)"], + [Blockly.Msg.MIXLY_LCD_BACKLIGHT, "backlight(on)"] + ]), "STAT"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('STAT'); + var mode0 = Blockly.Msg.LISTS_SET_INDEX_SET; + var mode1 = Blockly.Msg.MIXLY_DF_LCD; + var TOOLTIPS = { + 'on()': Blockly.Msg.MIXLY_ON, + 'off()': Blockly.Msg.MIXLY_OFF, + 'clear()': Blockly.Msg.MIXLY_LCD_STAT_CLEAR, + 'backlight(off)': Blockly.Msg.MIXLY_LCD_NOBACKLIGHT, + 'backlight(on)': Blockly.Msg.MIXLY_LCD_BACKLIGHT + }; + return mode0 + mode1 + TOOLTIPS[mode]; + }); + } +}; + +// export const oled_init = { +// init: function() { +// this.setColour(DISPLAY_HUE); +// this.appendValueInput('VAR') +// .appendField(Blockly.Msg.OLED) +// .setCheck("var"); +// this.appendValueInput("RX", Number) +// //.appendField(Blockly.Msg.MIXLY_SETUP) +// // .appendField(Blockly.Msg.OLED) +// // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') +// .appendField(Blockly.Msg.MIXLY_SETUP) +// .appendField("sda") +// .setCheck(Number) +// .setAlign(Blockly.inputs.Align.RIGHT); +// this.appendValueInput("TX", Number) +// .appendField("scl") +// .setCheck(Number) +// .setAlign(Blockly.inputs.Align.RIGHT); +// this.appendValueInput('freq') +// .setCheck(Number) +// .appendField(Blockly.Msg.MIXLY_FREQUENCY) +// .setAlign(Blockly.inputs.Align.RIGHT); +// this.setPreviousStatement(true, null); +// this.setNextStatement(true, null); +// this.setInputsInline(true); +// } +// }; + +export const display_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + // this.appendDummyInput("") + // .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO + "OLED") + // .appendField(new Blockly.FieldDropdown([ + // ["OLED 128¡Á64", "OLED 128¡Á64"] + // ]), "key"); + this.appendValueInput('row') + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO + "OLED") + .setCheck(Number); + this.appendValueInput('column') + .appendField("X") + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(); + } +}; + +export const display_draw_4strings = { + init: function () { + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // this.appendDummyInput("") + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + // .appendField(Blockly.Msg.OLEDDISPLAY); + //.appendField(new Blockly.FieldImage(Blockly.pathToBlockly + 'blocks/display-oled-128x64-i2c/display-oled-128x64-i2c.jpg', Blockly.Arduino.imageSize, Blockly.Arduino.imageSize)); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendValueInput("Text_line1", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.OLEDDISPLAY + Blockly.Msg.line1); + this.appendValueInput("Text_line2", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.line2); + this.appendValueInput("Text_line3", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.line3); + this.appendValueInput("Text_line4", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.line4); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setColour(DISPLAY_HUE); + this.setTooltip(Blockly.Msg.MIXLY_DF_LCD + Blockly.Msg.OLEDDISPLAY + Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING); + } +}; + +export const display_image_size = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_MICROBIT_IMAGE); + this.appendValueInput('VAR') + .setCheck("esp32_image") + // .appendField(Blockly.Msg.blockpy_USE_LIST); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(display_image_size.OPERATORS), 'OP'); + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_IMAGE + var TOOLTIPS = { + 'height': Blockly.Msg.MIXLY_HEIGHT, + 'width': Blockly.Msg.MIXLY_WIDTH, + }; + return mode0 + mode1 + TOOLTIPS[mode]; + }); + }, + OPERATORS: [ + [Blockly.Msg.MIXLY_HEIGHT, 'height'], + [Blockly.Msg.MIXLY_WIDTH, 'width'] + ] +}; + +export const display_rect = { + init: function () { + this.setColour(DISPLAY_HUE); + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RECT) + .appendField(new Blockly.FieldDropdown(display_rect.STATUS), 'OP') + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_RECT, + "args0": [{ + "check": Number, + "type": "input_value", + "name": "x" + }, { + "check": Number, + "type": "input_value", + "name": "y" + }, { + "check": Number, + "type": "input_value", + "name": "width" + }, { + "check": Number, + "type": "input_value", + "name": "height" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "fill" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_OLED_RECT); + }, + STATUS: [ + [Blockly.Msg.MIXLY_4DIGITDISPLAY_ON, '1'], + [Blockly.Msg.MIXLY_4DIGITDISPLAY_OFF, '0'] + ] +}; + +export const display_line = { + init: function () { + this.setColour(DISPLAY_HUE); + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DISPLAY_DRAW) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_DISPLAY_RLINE, "hline"], + [Blockly.Msg.MIXLY_DISPLAY_VLINE, "vline"] + ]), "direction"); + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_LINE, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x" + }, { + "check": Number, + "type": "input_value", + "name": "y" + }, { + "check": Number, + "type": "input_value", + "name": "length" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_OLED_LINE); + } +}; + +export const display_line_arbitrarily = { + init: function () { + this.setColour(DISPLAY_HUE); + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_LINE_ARBITRARILY, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x1" + }, { + "check": Number, + "type": "input_value", + "name": "y1" + }, { + "check": Number, + "type": "input_value", + "name": "x2" + }, { + "check": Number, + "type": "input_value", + "name": "y2" + }, + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_OLED_LINE_ARBIT); + } +} + +export const display_get_screen_pixel = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + } +}; + +export const display_get_screen_image = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_GET_SCREEN_IMAGE); + this.setInputsInline(true); + this.setOutput(true, "esp32_image"); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MONITOR_GET_SCREEN_IMAGE_TOOLTIP); + } +}; + +export const display_bright_screen = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS); + } +}; + +export const display_blink_rate = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BLINK_RATE) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BLINK_RATE); + } +}; + +export const display_rgb_color = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendDummyInput("") + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_AS) + .appendField(new Blockly.FieldColour('#f00', null, FIELD_COLOUR_CONFIG), 'FIELDNAME'); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B); + } +}; + +export const display_show_image_or_string = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('data') + .setCheck([String, "esp32_image", "List", 'Tuple']) + .appendField(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_OR_ANIMATION); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const display_scroll_string = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const display_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('data') + .setCheck([String, "esp32_image", "List", 'Tuple']) + .appendField(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_OR_ANIMATION); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_DELAY); + } +}; + +export const display_scroll_string_delay = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SCROLL_IMAGE_OR_STRING_DELAY); + } +}; + +export const display_onoff = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_ON, "ON"], + [Blockly.Msg.MIXLY_ESP32_OFF, "OFF"] + ]), 'ONOFF') + this.setOutput(true, Boolean); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +// export const switch = { +// init: function () { +// this.setColour(DISPLAY_HUE); +// this.appendDummyInput("") +// .appendField(new Blockly.FieldDropdown([ +// [Blockly.Msg.MIXLY_ESP32_ON, "1"], +// [Blockly.Msg.MIXLY_ESP32_OFF, "0"] +// ]), "flag"); +// this.setOutput(true); +// this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); +// } +// }; + +export const display_fill = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('SUB'); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LCD_STAT_CLEAR, "0"], + [Blockly.Msg.MIXLY_HANDBIT_DISLPAY_OLED_FILL, "1"] + ]), "key"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + '0': Blockly.Msg.MIXLY_LCD_STAT_CLEAR, + '1': Blockly.Msg.MIXLY_HANDBIT_DISLPAY_OLED_FILL + }; + return Blockly.Msg.MIXLY_DF_LCD + TOOLTIPS[mode]; + }); + } +}; + +export const display_tm_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + // ["MPU9250", "MPU9250"], + // ["TM1637", "TM1637"], + ["TM1650", "TM1650"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_USE_I2C_TOOLTIP; + var TOOLTIPS = { + // "MPU9250": "MPU9250", + // "TM1637": "TM1637", + "TM1650": "TM1650" + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const display_tm1650_power = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY) + .appendField(new Blockly.FieldDropdown([["TM1650", "tm1650"]]), "TYPE"); + this.appendValueInput("VAR") + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ON, "_on"], + [Blockly.Msg.MIXLY_OFF, "_off"], + [Blockly.Msg.MIXLY_LCD_STAT_CLEAR, "_clear"] + ]), "STAT"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_4digitdisplay_power); + } +}; + +export const display_tm1650_show_num = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY) + .appendField(new Blockly.FieldDropdown([["TM1650", "tm1650"]]), "TYPE"); + this.appendValueInput("VAR") + this.appendValueInput("VALUE") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SHOW_NUMBER); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + // this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_4digitdisplay_displayString); + } +}; + +export const display_tm1650_show_dot = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY) + .appendField(new Blockly.FieldDropdown([["TM1650", "tm1650"]]), "TYPE"); + this.appendValueInput("VAR") + this.appendValueInput("NO") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1) + this.appendValueInput("STAT") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.MIXLY_4DIGITDISPLAY_DOT) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_4digitdisplay_showDot); + } +}; + +export const display_animate = { + init: function () { + this.setColour(DISPLAY_HUE); + this.setOutput(true, 'Tuple'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_DISPLAY_ANIMATE) + .appendField(new Blockly.FieldDropdown(display_animate.ANIMATE), 'ANIMATION') + //this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP); + }, + ANIMATE: [ + ["ALL_CLOCKS", 'ALL_CLOCKS'], + ["ALL_ARROWS", 'ALL_ARROWS'] + ] +}; + +export const display_circle = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MIXPY_TURTLE_DRAW_CIRCLE) + .appendField(new Blockly.FieldDropdown(display_circle.STATUS), 'OP') + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_HANBIT_SHOW_CIRCLE, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x" + }, { + "check": Number, + "type": "input_value", + "name": "y" + }, { + "check": Number, + "type": "input_value", + "name": "r" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "fill" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TURTLE_DRAW_CIRCLE); + }, + STATUS: [ + [Blockly.Msg.MIXLY_4DIGITDISPLAY_ON, '1'], + [Blockly.Msg.MIXLY_4DIGITDISPLAY_OFF, '0'] + ] +}; + +export const display_triangle = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DISPLAY_DRAW + Blockly.Msg.MIXLY_HANBIT_DRAW_TRIANGLE) + .appendField(new Blockly.FieldDropdown(display_triangle.STATUS), 'OP') + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_HANBIT_SHOW_triangle, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x0" + }, { + "check": Number, + "type": "input_value", + "name": "y0" + }, { + "check": Number, + "type": "input_value", + "name": "x1" + }, { + "check": Number, + "type": "input_value", + "name": "y1" + }, { + "check": Number, + "type": "input_value", + "name": "x2" + }, { + "check": Number, + "type": "input_value", + "name": "y2" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "fill" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_DISPLAY_DRAW + Blockly.Msg.MIXLY_HANBIT_DRAW_TRIANGLE); + }, + STATUS: [ + [Blockly.Msg.MIXLY_4DIGITDISPLAY_ON, '1'], + [Blockly.Msg.MIXLY_4DIGITDISPLAY_OFF, '0'] + ] +}; + +export const display_help = { + init: function () { + this.setColour('#555555'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXGO_ONBOARDDISPLAY_HELP); + this.setInputsInline(true); + this.setTooltip(''); + } +}; + +//显示-OLED-显示图像 +export const display_oled_showBitmap = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.OLED_BITMAP); + this.appendValueInput("START_X", Number) + .appendField(Blockly.Msg.OLED_START_X) + .setCheck(Number); + this.appendValueInput("START_Y", Number) + .appendField(Blockly.Msg.OLED_START_Y) + .setCheck(Number); + this.appendValueInput("bitmap_name", String) + .appendField(Blockly.Msg.OLED_BITMAP_NAME); + this.appendValueInput("WIDTH", Number) + .appendField(Blockly.Msg.MIXLY_WIDTH) + .setCheck(Number); + this.appendValueInput("HEIGHT", Number) + .appendField(Blockly.Msg.MIXLY_HEIGHT) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.OLED_SHOW_BMP_TOOLTIP); + } +}; + +//显示-OLED-画点 +export const display_oled_drawPixel = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + this.appendDummyInput("") + .appendField(Blockly.Msg.OLED_DRAWPIXEL); + this.appendValueInput("POS_X") + .appendField(Blockly.Msg.OLED_POSX) + this.appendValueInput("POS_Y") + .appendField(Blockly.Msg.OLED_POSY) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.OLED_DRAW_PIXE_TOOLTIP); + } +}; + +//pe: +export const display_matrix_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + ["32x12 Matrix", "32x12 Matrix"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const display_show_image = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('SUB') + this.appendValueInput('data') + .setCheck([String, "esp32_image", "List", 'Tuple']) + .appendField(Blockly.Msg.OLED_BITMAP); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const display_scroll_string_extern = { + init: function () { + this.setColour(DISPLAY_HUE); + this.appendValueInput('SUB'); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/display_extern.js b/mixly/boards/default_src/micropython/blocks/display_extern.js new file mode 100644 index 00000000..063655a5 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/display_extern.js @@ -0,0 +1,1774 @@ +import * as Blockly from 'blockly/core'; + +const DISPLAY_EXTERN_HUE = '5BA5A5'; + +//var IMG = [["HEART", "HEART"],["HEART_SMALL", "HEART_SMALL"],["HAPPY", "HAPPY"],["SAD", "SAD"],["SMILE", "SMILE"],["SILLY", "SILLY"],["FABULOUS", "FABULOUS"],["SURPRISED", "SURPRISED"],["ASLEEP", "ASLEEP"],["ANGRY", "ANGRY"],["CONFUSED", "CONFUSED"],["NO", "NO"],["YES", "YES"],["LEFT_ARROW", "LEFT_ARROW"],["RIGHT_ARROW", "RIGHT_ARROW"],["DRESS", "DRESS"],["TRANSFORMERS", "TRANSFORMERS"],["SCISSORS", "SCISSORS"],["EXIT", "EXIT"],["TREE", "TREE"],["PACMAN", "PACMAN"],["TARGET", "TARGET"],["TSHIRT", "TSHIRT"],["ROLLERSKATE", "ROLLERSKATE"],["DUCK", "DUCK"],["HOUSE", "HOUSE"],["TORTOISE", "TORTOISE"],["BUTTERFLY", "BUTTERFLY"],["STICKFIGURE", "STICKFIGURE"],["GHOST", "GHOST"],["PITCHFORK", "PITCHFORK"],["MUSIC_QUAVERS", "MUSIC_QUAVERS"],["MUSIC_QUAVER", "MUSIC_QUAVER"],["MUSIC_CROTCHET", "MUSIC_CROTCHET"],["COW", "COW"],["RABBIT", "RABBIT"],["SQUARE_SMALL", "SQUARE_SMALL"],["SQUARE", "SQUARE"],["DIAMOND_SMALL", "DIAMOND_SMALL"],["DIAMOND", "DIAMOND"],["CHESSBOARD", "CHESSBOARD"],["TRIANGLE_LEFT", "TRIANGLE_LEFT"],["TRIANGLE", "TRIANGLE"],["SNAKE", "SNAKE"],["UMBRELLA", "UMBRELLA"],["SKULL", "SKULL"],["GIRAFFE", "GIRAFFE"],["SWORD", "SWORD"]]; +// var IMG = [["HEART", "HEART"], ["HEART_SMALL", "HEART_SMALL"], ["HAPPY", "HAPPY"], ["SAD", "SAD"], ["SMILE", "SMILE"], ["SILLY", "SILLY"], ["FABULOUS", "FABULOUS"], ["SURPRISED", "SURPRISED"], ["ASLEEP", "ASLEEP"], ["ANGRY", "ANGRY"], ["CONFUSED", "CONFUSED"], ["NO", "NO"], ["YES", "YES"]]; + +export const display_matrix_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + ["32x12 Matrix", "32x12 Matrix"], + ["16x8 Matrix", "16x8 Matrix"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const display_matrix_extern_show_image = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('data') + .setCheck([String, "esp32_image", "List", 'Tuple']) + .appendField(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const display_matrix_extern_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendDummyInput("") + .appendField(Blockly.Msg.TEXT_CENTER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'center') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_DELAY); + } +}; + +export const display_matrix_extern_scroll_string = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const display_matrix_extern_scroll_string_delay = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SCROLL_IMAGE_OR_STRING_DELAY); + } +}; + +export const display_matrix_extern_show_frame_string = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const display_matrix_extern_show_frame_string_delay = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const display_matrix_extern_shift = { + init: function () { + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + // this.setOutput(true); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET) + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .appendField(new Blockly.FieldDropdown(display_matrix_extern_shift.OPERATORS), 'OP'); + this.appendValueInput('val') + .appendField(Blockly.Msg.DISPLAY_IMAGE_SHIFT) + .setCheck(Number); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_UNIT) + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var mode0 = Blockly.Msg.DISPLAY_IMAGE_LET; + var mode1 = Blockly.Msg.DISPLAY_IMAGE_LET2; + var mode2 = Blockly.Msg.DISPLAY_IMAGE_LET3; + var TOOLTIPS = { + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT + }; + return mode0 + mode1 + TOOLTIPS[mode] + mode2; + }); + }, + OPERATORS: [ + [Blockly.Msg.MIXLY_UP, 'shift_up'], + [Blockly.Msg.MIXLY_DOWN, 'shift_down'], + [Blockly.Msg.MIXLY_LEFT, 'shift_left'], + [Blockly.Msg.MIXLY_RIGHT, 'shift_right'], + ] +}; + +export const display_matrix_extern_get_pixel = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_POINT); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_BRIGHTNESS); + } +}; + +export const display_matrix_extern_bright_point = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BRIGHTNESS) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendValueInput("STAT") + .setCheck([Number, Boolean]); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_DISPLAY_SETPIXEL); + } +}; + +export const display_matrix_extern_get_screen_pixel = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + } +}; + +export const display_matrix_extern_bright_screen = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS + ' 0.0-1.0'); + } +}; + +export const display_matrix_extern_clear = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + } +}; + + +export const display_matrix_extern_image_builtins = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Built_in_image1) + .appendField(new Blockly.FieldDropdown(display_matrix_extern_image_builtins.OPERATORS), 'image'); + this.setOutput(true, "esp32_image"); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + }, + OPERATORS: [ + ["HEART", "HEART"], + ["HEART_SMALL", "HEART_SMALL"], + ["HAPPY", "HAPPY"], + ["SAD", "SAD"], + ["SMILE", "SMILE"], + ["SILLY", "SILLY"], + ["FABULOUS", "FABULOUS"], + ["SURPRISED", "SURPRISED"], + ["ASLEEP", "ASLEEP"], + ["ANGRY", "ANGRY"], + ["CONFUSED", "CONFUSED"], + ["NO", "NO"], + ["YES", "YES"] + ] +}; + +export const matrix_extern_image_arithmetic = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.setOutput(true, "esp32_image"); + this.appendValueInput('A') + // .setCheck(["esp32_image", "List", String]) + .appendField(Blockly.Msg.MICROBIT_DISPLAY_MERGE_SHAPE); + this.appendValueInput('B') + // .setCheck(["esp32_image", "List", String]) + .appendField(new Blockly.FieldDropdown(matrix_extern_image_arithmetic.OPERATORS), 'OP'); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + '+': Blockly.Msg.MIXLY_MICROBIT_image_add, + '-': Blockly.Msg.MIXLY_MICROBIT_image_reduce + }; + return TOOLTIPS[mode]; + }); + }, + OPERATORS: [ + [Blockly.Msg.MICROBIT_DISPLAY_UNION, 'add'], + [Blockly.Msg.MICROBIT_DISPLAY_MINUS, 'sub'] + ] +}; + +export const matrix_extern_image_invert = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var"); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('A') + .setCheck("esp32_image") + .appendField(Blockly.Msg.MIXLY_MICROBIT_Invert_image1); + this.setInputsInline(true); + this.setOutput(true, "esp32_image"); + } +}; + +//oled +export const display_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + // this.appendDummyInput("") + // .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO + "OLED") + // .appendField(new Blockly.FieldDropdown([ + // ["OLED 128¡Á64", "OLED 128¡Á64"] + // ]), "key"); + this.appendValueInput('row') + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO + "OLED") + .setCheck(Number); + this.appendValueInput('column') + .appendField("X") + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(); + } +}; + +export const display_draw_4strings = { + init: function () { + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // this.appendDummyInput("") + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + // .appendField(Blockly.Msg.OLEDDISPLAY); + //.appendField(new Blockly.FieldImage(Blockly.pathToBlockly + 'blocks/display-oled-128x64-i2c/display-oled-128x64-i2c.jpg', Blockly.Arduino.imageSize, Blockly.Arduino.imageSize)); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendValueInput("Text_line1", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.OLEDDISPLAY + Blockly.Msg.line1); + this.appendValueInput("Text_line2", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.line2); + this.appendValueInput("Text_line3", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.line3); + this.appendValueInput("Text_line4", 'String') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.line4); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setColour(DISPLAY_EXTERN_HUE); + this.setTooltip(Blockly.Msg.MIXLY_DF_LCD + Blockly.Msg.OLEDDISPLAY + Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING); + } +}; + +export const display_image_size = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_MICROBIT_IMAGE); + this.appendValueInput('VAR') + .setCheck("esp32_image") + // .appendField(Blockly.Msg.blockpy_USE_LIST); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(display_image_size.OPERATORS), 'OP'); + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_IMAGE + var TOOLTIPS = { + 'height': Blockly.Msg.MIXLY_HEIGHT, + 'width': Blockly.Msg.MIXLY_WIDTH, + }; + return mode0 + mode1 + TOOLTIPS[mode]; + }); + }, + OPERATORS: [ + [Blockly.Msg.MIXLY_HEIGHT, 'height'], + [Blockly.Msg.MIXLY_WIDTH, 'width'] + ] +}; + +export const display_rect = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RECT) + .appendField(new Blockly.FieldDropdown(display_rect.STATUS), 'OP') + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_RECT, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x" + }, { + "check": Number, + "type": "input_value", + "name": "y" + }, { + "check": Number, + "type": "input_value", + "name": "width" + }, { + "check": Number, + "type": "input_value", + "name": "height" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "fill" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_OLED_RECT); + }, + STATUS: [ + [Blockly.Msg.MIXLY_4DIGITDISPLAY_ON, '1'], + [Blockly.Msg.MIXLY_4DIGITDISPLAY_OFF, '0'] + ] +}; + +export const display_line = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DISPLAY_DRAW) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_DISPLAY_RLINE, "hline"], + [Blockly.Msg.MIXLY_DISPLAY_VLINE, "vline"] + ]), "direction"); + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_LINE, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x" + }, { + "check": Number, + "type": "input_value", + "name": "y" + }, { + "check": Number, + "type": "input_value", + "name": "length" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_OLED_LINE); + } +}; + +export const display_line_arbitrarily = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_LINE_ARBITRARILY, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x1" + }, { + "check": Number, + "type": "input_value", + "name": "y1" + }, { + "check": Number, + "type": "input_value", + "name": "x2" + }, { + "check": Number, + "type": "input_value", + "name": "y2" + }, + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_OLED_LINE_ARBIT); + } +} + +export const display_get_screen_image = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_GET_SCREEN_IMAGE); + this.setInputsInline(true); + this.setOutput(true, "esp32_image"); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_MONITOR_GET_SCREEN_IMAGE_TOOLTIP); + } +}; + +export const display_blink_rate = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BLINK_RATE) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BLINK_RATE); + } +}; + +export const display_rgb_color = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RGB) + this.appendValueInput("_LED_") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RGB_NUM); + this.appendDummyInput("") + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_AS) + .appendField(new Blockly.FieldColour('#000', null, { + colourOptions: ['#f00', '#000'], + columns: 2 + }), 'FIELDNAME'); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_RGB_NUM_R_G_B); + } +}; + +export const display_onoff = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_ON, "ON"], + [Blockly.Msg.MIXLY_ESP32_OFF, "OFF"] + ]), 'ONOFF') + this.setOutput(true, Boolean); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +// export const switch = { +// init: function () { +// this.setColour(DISPLAY_EXTERN_HUE); +// this.appendDummyInput("") +// .appendField(new Blockly.FieldDropdown([ +// [Blockly.Msg.MIXLY_ESP32_ON, "1"], +// [Blockly.Msg.MIXLY_ESP32_OFF, "0"] +// ]), "flag"); +// this.setOutput(true); +// this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); +// } +// }; + +export const display_fill = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LCD_STAT_CLEAR, "0"], + [Blockly.Msg.MIXLY_HANDBIT_DISLPAY_OLED_FILL, "1"] + ]), "key"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + '0': Blockly.Msg.MIXLY_LCD_STAT_CLEAR, + '1': Blockly.Msg.MIXLY_HANDBIT_DISLPAY_OLED_FILL + }; + return Blockly.Msg.MIXLY_DF_LCD + TOOLTIPS[mode]; + }); + } +}; + +export const display_animate = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.setOutput(true, 'Tuple'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_DISPLAY_ANIMATE) + .appendField(new Blockly.FieldDropdown(display_animate.ANIMATE), 'ANIMATION') + //this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP); + }, + ANIMATE: [ + ["ALL_CLOCKS", 'ALL_CLOCKS'], + ["ALL_ARROWS", 'ALL_ARROWS'] + ] +}; + +export const display_circle = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MIXPY_TURTLE_DRAW_CIRCLE) + .appendField(new Blockly.FieldDropdown(display_circle.STATUS), 'OP') + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_HANBIT_SHOW_CIRCLE, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x" + }, { + "check": Number, + "type": "input_value", + "name": "y" + }, { + "check": Number, + "type": "input_value", + "name": "r" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "fill" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TURTLE_DRAW_CIRCLE); + }, + STATUS: [ + [Blockly.Msg.MIXLY_4DIGITDISPLAY_ON, '1'], + [Blockly.Msg.MIXLY_4DIGITDISPLAY_OFF, '0'] + ] +}; + +export const display_triangle = { + init: function () { + var brightness_or_not = [ + [Blockly.Msg.MIXLY_4DIGITDISPLAY_ON, '1'], + [Blockly.Msg.MIXLY_4DIGITDISPLAY_OFF, '0'] + ]; + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DISPLAY_DRAW + Blockly.Msg.MIXLY_HANBIT_DRAW_TRIANGLE) + .appendField(new Blockly.FieldDropdown(brightness_or_not), 'OP') + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_HANBIT_SHOW_triangle, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x0" + }, { + "check": Number, + "type": "input_value", + "name": "y0" + }, { + "check": Number, + "type": "input_value", + "name": "x1" + }, { + "check": Number, + "type": "input_value", + "name": "y1" + }, { + "check": Number, + "type": "input_value", + "name": "x2" + }, { + "check": Number, + "type": "input_value", + "name": "y2" + }, { + "type": "input_dummy" + }, { + "checked": false, + "type": "field_checkbox", + "name": "fill" + } + ] + }); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(''); + this.setTooltip(Blockly.Msg.MIXLY_DISPLAY_DRAW + Blockly.Msg.MIXLY_HANBIT_DRAW_TRIANGLE); + } +}; + +export const display_help = { + init: function () { + this.setColour('#555555'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXGO_ONBOARDDISPLAY_HELP); + this.setInputsInline(true); + this.setTooltip(''); + } +}; + +//显示-OLED-显示图像 +export const display_oled_showBitmap = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.OLED_BITMAP); + this.appendValueInput("START_X", Number) + .appendField(Blockly.Msg.OLED_START_X) + .setCheck(Number); + this.appendValueInput("START_Y", Number) + .appendField(Blockly.Msg.OLED_START_Y) + .setCheck(Number); + this.appendValueInput("bitmap_name", String) + .appendField(Blockly.Msg.OLED_BITMAP_NAME); + this.appendValueInput("WIDTH", Number) + .appendField(Blockly.Msg.MIXLY_WIDTH) + .setCheck(Number); + this.appendValueInput("HEIGHT", Number) + .appendField(Blockly.Msg.MIXLY_HEIGHT) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.OLED_SHOW_BMP_TOOLTIP); + } +}; + +//显示-OLED-画点 +export const display_oled_drawPixel = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.OLED) + this.appendDummyInput("") + .appendField(Blockly.Msg.OLED_DRAWPIXEL); + this.appendValueInput("POS_X") + .appendField(Blockly.Msg.OLED_POSX) + this.appendValueInput("POS_Y") + .appendField(Blockly.Msg.OLED_POSY) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.OLED_DRAW_PIXE_TOOLTIP); + } +}; + +export const display_tm_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + // ["MPU9250", "MPU9250"], + ["TM1650", "TM1650"], + ["TM1637", "TM1637"] + ]), "key"); + this.appendValueInput('CLK') + .appendField('CLK#'); + this.appendValueInput('DIO') + .appendField('DIO#'); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_USE_I2C_TOOLTIP; + var TOOLTIPS = { + // "MPU9250": "MPU9250", + "TM1637": "TM1637", + "TM1650": "TM1650" + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const display_tm1650_power = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY) + .appendField(new Blockly.FieldDropdown([["TM1650", "tm1650"]]), "TYPE"); + this.appendValueInput("VAR") + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ON, "on"], + [Blockly.Msg.MIXLY_OFF, "off"], + [Blockly.Msg.MIXLY_LCD_STAT_CLEAR, "clear"] + ]), "STAT"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_4digitdisplay_power); + } +}; + +export const display_tm1650_show_num = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY) + .appendField(new Blockly.FieldDropdown([["TM1650", "tm1650"],["TM1637", "TM1637"]]), "TYPE"); + this.appendValueInput("VAR") + this.appendValueInput("VALUE") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SHOW_NUMBER); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + // this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_4digitdisplay_displayString); + } +}; + +export const display_tm1650_show_dot = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY) + .appendField(new Blockly.FieldDropdown([["TM1650", "tm1650"],["TM1637", "TM1637"]]), "TYPE"); + this.appendValueInput("VAR") + this.appendValueInput("NO") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER1) + this.appendValueInput("STAT") + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY_NOMBER2 + Blockly.Msg.MIXLY_4DIGITDISPLAY_DOT) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_4digitdisplay_showDot); + } +}; + +export const display_tm1650_set_brightness = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_4DIGITDISPLAY) + .appendField(new Blockly.FieldDropdown([["TM1650", "tm1650"],["TM1637", "TM1637"]]), "TYPE"); + this.appendValueInput("VAR") + this.appendValueInput("VALUE") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SET_BRIGHTNESS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_4DIGITDISPLAY_4DIGITDISPLAY_BRIGHTNESS_TOOLTIP); + } +}; + +export const tft_use_spi_init = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SPISUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "SPI") + .setCheck("var"); + this.appendValueInput('PINDC') + .appendField("DC") + this.appendValueInput('PINCS') + .appendField("CS") + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO + Blockly.Msg.MSG.catTFT) + this.appendValueInput("WIDTH") + .appendField(Blockly.Msg.MIXLY_WIDTH) + .setCheck(Number); + this.appendValueInput("HEIGHT") + .appendField(Blockly.Msg.MIXLY_HEIGHT) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_turtle_rotate) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "0"], + [Blockly.Msg.ANTI_CLOCKWISE + '90°', "1"], + [Blockly.Msg.ANTI_CLOCKWISE + '180°', "2"], + [Blockly.Msg.ANTI_CLOCKWISE + '270°', "3"] + ]), 'rotate') + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const tft_show_image_xy = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MSG.catTFT); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_NUMBER); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const display_color_seclet = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput("") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldColour('#000', null, { + colourOptions: [ + // grays + '#ffffff', '#cccccc', '#c0c0c0', '#999999', '#666666', '#333333', '#000000', + // reds + '#ffcccc', '#ff6666', '#ff0000', '#cc0000', '#990000', '#660000', '#330000', + // oranges + '#ffcc99', '#ff9966', '#ff9900', '#ff6600', '#cc6600', '#993300', '#663300', + // yellows + '#ffff99', '#ffff66', '#ffcc66', '#ffcc33', '#cc9933', '#996633', '#663333', + // olives + '#ffffcc', '#ffff33', '#ffff00', '#ffcc00', '#999900', '#666600', '#333300', + // greens + '#99ff99', '#66ff99', '#33ff33', '#33cc00', '#009900', '#006600', '#003300', + // turquoises + '#99ffff', '#33ffff', '#66cccc', '#00cccc', '#339999', '#336666', '#003333', + // blues + '#ccffff', '#66ffff', '#33ccff', '#3366ff', '#3333ff', '#000099', '#000066', + // purples + '#ccccff', '#9999ff', '#6666cc', '#6633ff', '#6600cc', '#333399', '#330099', + // violets + '#ffccff', '#ff99ff', '#cc66cc', '#cc33cc', '#993399', '#663366', '#330033' + ], + columns: 7 + }), "COLOR"); + this.setInputsInline(true); + this.setOutput(true, String); + } +}; + +export const tft_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MSG.catTFT); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendDummyInput("") + .appendField(Blockly.Msg.TEXT_CENTER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'center') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_DELAY); + } +}; + + +export const tft_scroll_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MSG.catTFT); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SCROLL_IMAGE_OR_STRING_DELAY); + } +}; + +export const tft_show_frame_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MSG.catTFT); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const tft_fill = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catTFT); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LCD_STAT_CLEAR, "BLACK"], + [Blockly.Msg.MIXLY_HANDBIT_DISLPAY_OLED_FILL, "WHITE"] + ]), "key"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + '0': Blockly.Msg.MIXLY_LCD_STAT_CLEAR, + '1': Blockly.Msg.MIXLY_HANDBIT_DISLPAY_OLED_FILL + }; + return Blockly.Msg.MIXLY_DF_LCD + TOOLTIPS[mode]; + }); + } +}; + +export const tft_line_arbitrarily = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + // this.appendDummyInput() + // .appendField(Blockly.Msg.OLED) + // .appendField(new Blockly.FieldTextInput('lcd'), 'VAR') + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MSG.catTFT) + .setCheck("var"); + // this.appendValueInput("PIN", Number) + // .setCheck(Number) + // .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField(Blockly.Msg.MIXLY_PIN); + this.jsonInit({ + "message0": Blockly.Msg.MIXLY_MICROBIT_SHOW_LINE_ARBITRARILY, + "args0": [ + { + "check": Number, + "type": "input_value", + "name": "x1" + }, { + "check": Number, + "type": "input_value", + "name": "y1" + }, { + "check": Number, + "type": "input_value", + "name": "x2" + }, { + "check": Number, + "type": "input_value", + "name": "y2" + }, + ] + }); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_OLED_LINE_ARBIT); + } +} + +export const display_lcd_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + // ["MPU9250", "MPU9250"], + // ["TM1637", "TM1637"], + ["LCD1602", "16"], + ["LCD2004", "20"] + ]), "key"); + this.appendValueInput("ADDR") + .setCheck(Number) + .appendField(Blockly.Msg.MQTT_SERVER_ADD); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_SETUP; + var TOOLTIPS = { + "16": "LCD1602", + "20": "LCD2004" + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const lcd_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MSG.catLCD); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("x") + .setCheck(Number) + .appendField(Blockly.Msg.array2_cols); + this.appendValueInput("y") + .setCheck(Number) + .appendField(Blockly.Msg.array2_rows); + this.appendDummyInput("") + .appendField(Blockly.Msg.TEXT_CENTER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'center') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_DELAY); + } +}; + +export const lcd_print_string = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MSG.catLCD); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINT + Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("x") + .setCheck(Number) + .appendField(Blockly.Msg.array2_cols); + this.appendValueInput("y") + .setCheck(Number) + .appendField(Blockly.Msg.array2_rows); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const lcd_backlight = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catLCD); + this.appendDummyInput() + .appendField(Blockly.Msg.TFT_Brightness) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_Turn_on_display, "1"], + [Blockly.Msg.MIXLY_MICROBIT_Turn_off_display, "0"] + ]), "key"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + '1': Blockly.Msg.MIXLY_MICROBIT_Turn_on_display, + '0': Blockly.Msg.MIXLY_MICROBIT_Turn_off_display + }; + return Blockly.Msg.MSG.catLCD + Blockly.Msg.TFT_Brightness + TOOLTIPS[mode]; + }); + } +}; + +export const lcd_clear = { + init: function () { + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catLCD); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + } +}; + +export const display_oled_use_i2c_init = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO + 'oled128x64') + this.appendValueInput("ADDR") + .setCheck(Number) + .appendField(Blockly.Msg.MQTT_SERVER_ADD); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_DRIVER) + .appendField(new Blockly.FieldDropdown([ + ['SSD1306', '0'], + ['SSD1315', '1'] + ]), 'driver'); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_SETUP; + var TOOLTIPS = { + "16": "LCD1602", + "20": "LCD2004" + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const extern_oled_show_image = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const extern_oled_show_image_xy = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_NUMBER); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const extern_oled_show_string = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .setCheck([String, "esp32_image", "List", 'Tuple']) + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const extern_oled_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendDummyInput("") + .appendField(Blockly.Msg.TEXT_CENTER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'center') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_DELAY); + } +}; + +export const extern_oled_scroll_string = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const extern_oled_scroll_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SCROLL_IMAGE_OR_STRING_DELAY); + } +}; + +export const extern_oled_show_frame_string = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const extern_oled_show_frame_string_delay = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const extern_oled_shift = { + init: function () { + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + // this.setOutput(true); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET) + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .appendField(new Blockly.FieldDropdown(extern_oled_shift.OPERATORS), 'OP'); + this.appendValueInput('val') + .appendField(Blockly.Msg.DISPLAY_IMAGE_SHIFT) + .setCheck(Number); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_UNIT) + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var mode0 = Blockly.Msg.DISPLAY_IMAGE_LET; + var mode1 = Blockly.Msg.DISPLAY_IMAGE_LET2; + var mode2 = Blockly.Msg.DISPLAY_IMAGE_LET3; + var TOOLTIPS = { + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT + }; + return mode0 + mode1 + TOOLTIPS[mode] + mode2; + }); + }, + OPERATORS: [ + [Blockly.Msg.MIXLY_UP, 'shift_up'], + [Blockly.Msg.MIXLY_DOWN, 'shift_down'], + [Blockly.Msg.MIXLY_LEFT, 'shift_left'], + [Blockly.Msg.MIXLY_RIGHT, 'shift_right'], + ] +}; + +export const extern_oled_get_pixel = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_POINT); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_BRIGHTNESS); + } +}; + +export const extern_oled_bright_point = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BRIGHTNESS) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendValueInput("STAT") + .setCheck([Number, Boolean]); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_DISPLAY_SETPIXEL); + } +}; + +export const extern_oled_clear = { + init: function () { + this.setColour(DISPLAY_EXTERN_HUE); + this.appendValueInput('SUB') + .setCheck("var") + .appendField(Blockly.Msg.MSG.catOLED); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + } +}; + +export const extern_oled_shape_rect = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_EXTERN_HUE, + "args0": [ + { + "name": "SUB", + "type": "input_value" + }, + { + "name": "state", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_MODE_1, '1'], + [Blockly.Msg.MPYTHON_DISPLAY_MODE_0, '0'] + ], + "type": "field_dropdown" + }, + { + "name": "shape", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_HOLLOW, 'rect'], + [Blockly.Msg.MPYTHON_DISPLAY_SOLID, 'fill_rect'] + ], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, + { + "name": "x", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y", + "type": "input_value", + //"check": "Number" + }, + { + "name": "w", + "type": "input_value", + //"check": "Number" + }, + { + "name": "h", + "type": "input_value", + //"check": "Number" + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_DISPLAY_SHAPE_RECT_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_DISPLAY_SHAPE_RECT_MESSAGE1, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const extern_oled_hvline = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_EXTERN_HUE, + "args0": [ + { + "name": "SUB", + "type": "input_value" + }, + { + "name": "state", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_MODE_1, '1'], + [Blockly.Msg.MPYTHON_DISPLAY_MODE_0, '0'] + ], + "type": "field_dropdown" + }, + { + "name": "dir_h_v", + "options": [ + [Blockly.Msg.mpython_vertical, '0'], + [Blockly.Msg.mpython_horizontal, '1'] + ], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, + { + "name": "x", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y", + "type": "input_value", + //"check": "Number" + }, + { + "name": "length", + "type": "input_value", + //"check": "Number" + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_DISPLAY_HVLINE_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_DISPLAY_HVLINE_MESSAGE1, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const extern_oled_line = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_EXTERN_HUE, + "args0": [ + { + "name": "SUB", + "type": "input_value" + }, + { + "name": "state", + "options": [[Blockly.Msg.mpython_display_hline_1, '1'], [Blockly.Msg.mpython_display_hline_0, '0']], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, { + "name": "x1", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y1", + "type": "input_value", + //"check": "Number" + }, + { + "name": "x2", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y2", + "type": "input_value", + //"check": "Number" + } + + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.mpython_display_line_TOOLTIP, + "message0": Blockly.Msg.mpython_display_line_MESSAGE1, + "nextStatement": null, + "previousStatement": null + }); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/display_onboard.js b/mixly/boards/default_src/micropython/blocks/display_onboard.js new file mode 100644 index 00000000..732ea087 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/display_onboard.js @@ -0,0 +1,1743 @@ +import * as Blockly from 'blockly/core'; +import { Boards, Profile, JSFuncs } from 'mixly'; + +const DISPLAY_ONBOARD_HUE = '#569A98'; + +export const display_show_image = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .setCheck([String, "esp32_image", "List", 'Tuple']) + .appendField(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING); + var version = Boards.getSelectedBoardKey() + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + var version = Boards.getSelectedBoardKey() + if (version == 'micropython:esp32:mixbot') { + this.setTooltip(Blockly.Msg.MIXLY_MIXBOT_SHOW_SCROLL_STRING_TOOLTIP); + } + } +}; + +export const display_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendDummyInput("") + .appendField(Blockly.Msg.TEXT_CENTER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'center') + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + + } +}; + +export const display_scroll_string = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const display_scroll_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + var version = Boards.getSelectedBoardKey() + if (version == 'micropython:esp32s3:mixgo_nova') { + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + } + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + if (version == 'micropython:esp32s3:mixgo_nova') { + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SCROLL_IMAGE_OR_STRING_DELAY); + } +}; + +export const display_scroll_way = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_DISPLAY_SCROLL_WAY) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GAME_UP, "0"], + [Blockly.Msg.MIXLY_GAME_DOWN, "1"], + [Blockly.Msg.MIXLY_GAME_RIGHT, "2"], + [Blockly.Msg.MIXLY_GAME_LEFT, "3"] + ]), "way"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_scroll_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SCROLL_IMAGE_OR_STRING_DELAY); + } +}; + +export const display_show_frame_string = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const display_show_frame_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const display_image_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + for (let i = 0; i < 12; i++) { + let dummyInputObj = this.appendDummyInput(); + for (let j = 0; j < 32; j++) { + dummyInputObj.appendField(new Blockly.FieldColour('#000', null, { + colourOptions: ['#f00', '#000'], + columns: 2 + }), i + '-' + j); + } + } + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +export const display_bitmap_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + this.appendDummyInput('') + .setAlign(Blockly.inputs.Align.CENTRE) + .appendField(new Blockly.FieldBitmap(display_bitmap_create.BITMAP, null, { + filledColor: '#000', + emptyColor: '#5ba5a5', + bgColor: '#e5e7f1' + }), 'BITMAP'); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + }, + BITMAP: Array.from({ length: 12 }, () => new Array(32).fill(0)) +}; + +export const display_image_builtins = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "name": "image", + "options": [ + ["HEART", "HEART"], + ["HEART_SMALL", "HEART_SMALL"], + ["HAPPY", "HAPPY"], + ["SAD", "SAD"], + ["SMILE", "SMILE"], + ["SILLY", "SILLY"], + ["FABULOUS", "FABULOUS"], + ["SURPRISED", "SURPRISED"], + ["ASLEEP", "ASLEEP"], + ["ANGRY", "ANGRY"], + ["CONFUSED", "CONFUSED"], + ["NO", "NO"], + ["YES", "YES"] + ], + "type": "field_dropdown" + } + ], + "output": ["esp32_image", "List"], + "helpUrl": "https://microbit-micropython.readthedocs.io/en/latest/image.html#attributes", + "tooltip": Blockly.Msg.MIXLY_MICROBIT_Built_in_image1, + "message0": Blockly.Msg.MIXLY_MICROBIT_Built_in_image + }); + } +}; + +export const display_image_builtins_all = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_Built_in_image1) + .appendField(new Blockly.FieldDropdown(Profile.default.builtinimg), 'image'); + this.setOutput(true, ["esp32_image", "List"]); + } +}; + +export const image_arithmetic = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.setOutput(true, "esp32_image"); + this.appendValueInput('A') + // .setCheck(["esp32_image", "List", String]) + .appendField(Blockly.Msg.MICROBIT_DISPLAY_MERGE_SHAPE); + this.appendValueInput('B') + // .setCheck(["esp32_image", "List", String]) + .appendField(new Blockly.FieldDropdown(image_arithmetic.OPERATORS), 'OP'); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + '+': Blockly.Msg.MIXLY_MICROBIT_image_add, + '-': Blockly.Msg.MIXLY_MICROBIT_image_reduce + }; + return TOOLTIPS[mode]; + }); + }, + OPERATORS: [ + [Blockly.Msg.MICROBIT_DISPLAY_UNION, 'add'], + [Blockly.Msg.MICROBIT_DISPLAY_MINUS, 'sub'] + ] +}; + +export const image_invert = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('A') + .setCheck("esp32_image") + .appendField(Blockly.Msg.MIXLY_MICROBIT_Invert_image1); + this.setInputsInline(true); + this.setOutput(true, "esp32_image"); + } +}; + +export const display_shift = { + init: function () { + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(DISPLAY_ONBOARD_HUE); + // this.setOutput(true); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET) + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .appendField(new Blockly.FieldDropdown(display_shift.OPERATORS), 'OP'); + this.appendValueInput('val') + .appendField(Blockly.Msg.DISPLAY_IMAGE_SHIFT) + .setCheck(Number); + this.appendDummyInput('') + .appendField(Blockly.Msg.DISPLAY_IMAGE_UNIT) + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var mode0 = Blockly.Msg.DISPLAY_IMAGE_LET; + var mode1 = Blockly.Msg.DISPLAY_IMAGE_LET2; + var mode2 = Blockly.Msg.DISPLAY_IMAGE_LET3; + var TOOLTIPS = { + 'shift_up': Blockly.Msg.MIXLY_UP, + 'shift_down': Blockly.Msg.MIXLY_DOWN, + 'shift_left': Blockly.Msg.MIXLY_LEFT, + 'shift_right': Blockly.Msg.MIXLY_RIGHT + }; + return mode0 + mode1 + TOOLTIPS[mode] + mode2; + }); + }, + OPERATORS: [ + [Blockly.Msg.MIXLY_UP, 'shift_up'], + [Blockly.Msg.MIXLY_DOWN, 'shift_down'], + [Blockly.Msg.MIXLY_LEFT, 'shift_left'], + [Blockly.Msg.MIXLY_RIGHT, 'shift_right'], + ] +}; + +export const display_get_pixel = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_POINT); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_BRIGHTNESS); + } +}; + +export const display_bright_point = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BRIGHTNESS) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendValueInput("STAT") + .setCheck([Number, Boolean]); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_DISPLAY_SETPIXEL); + } +}; + +export const display_get_screen_pixel = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + } +}; + +export const display_bright_screen = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS + ' 0.0-1.0'); + } +}; + +export const display_clear = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Clear_display); + } +}; + +export const display_available = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SHOW + Blockly.Msg.MIXLY_DISPLAY_MATRIX_WRITE_NOW); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const mixgome_display_image_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + for (let i = 0; i < 5; i++) { + let dummyInputObj = this.appendDummyInput(); + for (let j = 0; j < 8; j++) { + dummyInputObj.appendField(new Blockly.FieldColour('#000', null, { + colourOptions: ['#f00', '#000'], + columns: 2 + }), i + '-' + j); + } + } + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +export const mixgome_display_bitmap_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + this.appendDummyInput('') + .setAlign(Blockly.inputs.Align.CENTRE) + .appendField(new Blockly.FieldBitmap(mixgome_display_bitmap_create.BITMAP, null, { + filledColor: '#000', + emptyColor: '#5ba5a5', + bgColor: '#e5e7f1' + }), 'BITMAP'); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + }, + BITMAP: Array.from({ length: 5 }, () => new Array(8).fill(0)) +}; + +/** + * @deprecated To be removed in the future + */ +export const mixgomini_display_image_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + for (let i = 0; i < 8; i++) { + let dummyInputObj = this.appendDummyInput(); + for (let j = 0; j < 12; j++) { + dummyInputObj.appendField(new Blockly.FieldColour('#000', null, { + colourOptions: ['#f00', '#000'], + columns: 2 + }), i + '-' + j); + } + } + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +export const mixgomini_display_bitmap_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + this.appendDummyInput('') + .setAlign(Blockly.inputs.Align.CENTRE) + .appendField(new Blockly.FieldBitmap(mixgomini_display_bitmap_create.BITMAP, null, { + filledColor: '#000', + emptyColor: '#5ba5a5', + bgColor: '#e5e7f1' + }), 'BITMAP'); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + }, + BITMAP: Array.from({ length: 8 }, () => new Array(12).fill(0)) +}; + +/** + * @deprecated To be removed in the future + */ +export const mixgo_display_image_create_new = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + for (let i = 0; i < 8; i++) { + let dummyInputObj = this.appendDummyInput(); + for (let j = 0; j < 16; j++) { + dummyInputObj.appendField(new Blockly.FieldColour('#000', null, { + colourOptions: ['#f00', '#000'], + columns: 2 + }), i + '-' + j); + } + } + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setOutput(true, "esp32_image"); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +export const mixgo_display_bitmap_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + this.appendDummyInput('') + .setAlign(Blockly.inputs.Align.CENTRE) + .appendField(new Blockly.FieldBitmap(mixgo_display_bitmap_create.BITMAP, null, { + filledColor: '#000', + emptyColor: '#5ba5a5', + bgColor: '#e5e7f1' + }), 'BITMAP'); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + }, + BITMAP: Array.from({ length: 8 }, () => new Array(16).fill(0)) +}; + +export const mixgome_display_font = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.OLED_SET_FONT) + .appendField(new Blockly.FieldDropdown(mixgome_display_font.OPERATORS), 'OP'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + }, + OPERATORS: [ + ['4x5' + Blockly.Msg.MIXGO_ME_DISPLAY_HORIZONTAL, "'4x5'"], + ['5x5' + Blockly.Msg.MIXGO_ME_DISPLAY_HORIZONTAL, "'5x5'"], + ['5x8' + Blockly.Msg.MIXGO_ME_DISPLAY_VERTICAL, "'5x8'"] + ] +}; + +//mpython + +export const onboard_oled_show_image = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const onboard_oled_show_image_xy = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_NUMBER); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const onboard_oled_show_string = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .setCheck([String, "esp32_image", "List", 'Tuple']) + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + } +}; + +export const onboard_oled_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendDummyInput("") + .appendField(Blockly.Msg.TEXT_CENTER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'center') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_DELAY); + } +}; + +export const onboard_oled_scroll_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_STRING); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SCROLL_IMAGE_OR_STRING_DELAY); + } +}; + +export const onboard_oled_show_frame_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_oled_bright_point = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_BRIGHTNESS) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendValueInput("STAT") + .setCheck([Number, Boolean]); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_DISPLAY_SETPIXEL); + } +}; + +export const mpython_display_shape_rect = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "name": "state", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_MODE_1, '1'], + [Blockly.Msg.MPYTHON_DISPLAY_MODE_0, '0'] + ], + "type": "field_dropdown" + }, + { + "name": "shape", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_HOLLOW, 'rect'], + [Blockly.Msg.MPYTHON_DISPLAY_SOLID, 'fill_rect'] + ], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, + { + "name": "x", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y", + "type": "input_value", + //"check": "Number" + }, + { + "name": "w", + "type": "input_value", + //"check": "Number" + }, + { + "name": "h", + "type": "input_value", + //"check": "Number" + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_DISPLAY_SHAPE_RECT_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_DISPLAY_SHAPE_RECT_MESSAGE0, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const mpython_display_hvline = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "name": "state", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_MODE_1, '1'], + [Blockly.Msg.MPYTHON_DISPLAY_MODE_0, '0'] + ], + "type": "field_dropdown" + }, + { + "name": "dir_h_v", + "options": [ + [Blockly.Msg.mpython_vertical, '0'], + [Blockly.Msg.mpython_horizontal, '1'] + ], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, + { + "name": "x", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y", + "type": "input_value", + //"check": "Number" + }, + { + "name": "length", + "type": "input_value", + //"check": "Number" + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_DISPLAY_HVLINE_TOOLTIP, + "message0": Blockly.Msg.MPYTHON_DISPLAY_HVLINE_MESSAGE0, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const mpython_display_line = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "name": "state", + "options": [[Blockly.Msg.mpython_display_hline_1, '1'], [Blockly.Msg.mpython_display_hline_0, '0']], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, { + "name": "x1", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y1", + "type": "input_value", + //"check": "Number" + }, + { + "name": "x2", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y2", + "type": "input_value", + //"check": "Number" + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.mpython_display_line_TOOLTIP, + "message0": Blockly.Msg.mpython_display_line_MESSAGE0, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const mpython_pbm_image = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Built_in_image1) + .appendField(new Blockly.FieldDropdown(mpython_pbm_image.IMAGES), 'path'); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setOutput(true); + }, + IMAGES: [ + ["Heart", "expression_picture.Heart"], + ["Angry", "expression_picture.Angry"], + ["Bored", "expression_picture.Bored"], + ["Confused", "expression_picture.Confused"], + ["Happy", "expression_picture.Happy"], + ["Paper", "expression_picture.Paper"], + ["Rock", "expression_picture.Rock"], + ["Sad", "expression_picture.Sad"], + ["Scissors", "expression_picture.Scissors"], + ["Silly", "expression_picture.Silly"], + ["Sleep", "expression_picture.Sleep"], + ["Small_heart", "expression_picture.Small_heart"], + ["Small_paper", "expression_picture.Small_paper"], + ["Small_rock", "expression_picture.Small_rock"], + ["Small_scissors", "expression_picture.Small_scissors"], + ["Smile", "expression_picture.Smile"], + ["Surprise", "expression_picture.Surprise"], + ["Wonderful", "expression_picture.Wonderful"], + ["Eyes_Angry", "eye_picture.Eyes_Angry"], + ["Awake", "eye_picture.Awake"], + ["Black_eye", "eye_picture.Black_eye"], + ["Bottom_left", "eye_picture.Bottom_left"], + ["Bottom_right", "eye_picture.Bottom_right"], + ["Crazy_1", "eye_picture.Crazy_1"], + ["Crazy_2", "eye_picture.Crazy_2"], + ["Disappointed", "eye_picture.Disappointed"], + ["Dizzy", "eye_picture.Dizzy"], + ["Down", "eye_picture.Down"], + ["Evil", "eye_picture.Evil"], + ["Hurt", "eye_picture.Hurt"], + ["Knocked_out", "eye_picture.Knocked_out"], + ["Love", "eye_picture.Love"], + ["Middle_left", "eye_picture.Middle_left"], + ["Middle_right", "eye_picture.Middle_right"], + ["Neutral", "eye_picture.Neutral"], + ["Nuclear", "eye_picture.Nuclear"], + ["Pinch_left", "eye_picture.Pinch_left"], + ["Pinch_middle", "eye_picture.Pinch_middle"], + ["Pinch_right", "eye_picture.Pinch_right"], + ["Tear", "eye_picture.Tear"], + ["Tired_left", "eye_picture.Tired_left"], + ["Tired_middle", "eye_picture.Tired_middle"], + ["Tired_right", "eye_picture.Tired_right"], + ["Toxic", "eye_picture.Toxic"], + ["Up", "eye_picture.Up"], + ["Winking", "eye_picture.Winking"], + ["Accept", "informatio_picture.Accept"], + ["Backward", "informatio_picture.Backward"], + ["Decline", "informatio_picture.Decline"], + ["Forward", "informatio_picture.Forward"], + ["Left", "informatio_picture.Left"], + ["No_go", "informatio_picture.No_go"], + ["Question_mark", "informatio_picture.Question_mark"], + ["Right", "informatio_picture.Right"], + ["Stop_1", "informatio_picture.Stop_1"], + ["Stop_2", "informatio_picture.Stop_2"], + ["Thumbs_down", "informatio_picture.Thumbs_down"], + ["Thumbs_up", "informatio_picture.Thumbs_up"], + ["Warning", "informatio_picture.Warning"], + ["Bomb", "object_picture.Bomb"], + ["Boom", "object_picture.Boom"], + ["Fire", "object_picture.Fire"], + ["Flowers", "object_picture.Flowers"], + ["Forest", "object_picture.Forest"], + ["Lightning", "object_picture.Lightning"], + ["Light_off", "object_picture.Light_off"], + ["Light_on", "object_picture.Light_on"], + ["Night", "object_picture.Night"], + ["Pirate", "object_picture.Pirate"], + ["Snow", "object_picture.Snow"], + ["Target", "object_picture.Target"], + ["Bar_0", "progres_picture.Bar_0"], + ["Bar_1", "progres_picture.Bar_1"], + ["Bar_2", "progres_picture.Bar_2"], + ["Bar_3", "progres_picture.Bar_3"], + ["Bar_4", "progres_picture.Bar_4"], + ["Dial_0", "progres_picture.Dial_0"], + ["Dial_1", "progres_picture.Dial_1"], + ["Dial_2", "progres_picture.Dial_2"], + ["Dial_3", "progres_picture.Dial_3"], + ["Dial_4", "progres_picture.Dial_4"], + ["Dots_0", "progres_picture.Dots_0"], + ["Dots_1", "progres_picture.Dots_1"], + ["Dots_2", "progres_picture.Dots_2"], + ["Dots_3", "progres_picture.Dots_3"], + ["Hourglass_0", "progres_picture.Hourglass_0"], + ["Hourglass_1", "progres_picture.Hourglass_1"], + ["Hourglass_2", "progres_picture.Hourglass_2"], + ["Timer_0", "progres_picture.Timer_0"], + ["Timer_1", "progres_picture.Timer_1"], + ["Timer_2", "progres_picture.Timer_2"], + ["Timer_3", "progres_picture.Timer_3"], + ["Timer_4", "progres_picture.Timer_4"], + ["Water_level_0", "progres_picture.Water_level_0"], + ["Water_level_1", "progres_picture.Water_level_1"], + ["Water_level_2", "progres_picture.Water_level_2"], + ["Water_level_3", "progres_picture.Water_level_3"], + ["YES", "informatio_picture.YES"], + ["NO", "informatio_picture.NO"] + ] +}; + +/** + * @deprecated To be removed in the future + */ +export const mixbot_display_image_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + for (let i = 0; i < 5; i++) { + let dummyInputObj = this.appendDummyInput(); + for (let j = 0; j < 5; j++) { + dummyInputObj.appendField(new Blockly.FieldColour('#000', null, { + colourOptions: ['#f00', '#000'], + columns: 2 + }), i + '-' + j); + } + } + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +export const mixbot_display_bitmap_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + this.appendDummyInput('') + .setAlign(Blockly.inputs.Align.CENTRE) + .appendField(new Blockly.FieldBitmap(mixbot_display_bitmap_create.BITMAP, null, { + filledColor: '#000', + emptyColor: '#5ba5a5', + bgColor: '#e5e7f1' + }), 'BITMAP'); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + }, + BITMAP: Array.from({ length: 5 }, () => new Array(5).fill(0)) +}; + +export const mixbot_display_get_screen_pixel = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_GET_SCREEN_BRIGHTNESS); + } +}; + +export const mixbot_display_get_ambientbright = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_AMBIENTBRIGHT); + this.setInputsInline(true); + this.setOutput(true, Number); + } +}; + +export const mixbot_display_bright_screen = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_SET_SCREEN_BRIGHTNESS + ' 0.0-1.0'); + } +}; + +export const mixbot_display_rotate = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_SCREEN_ROTATE) + .appendField(new Blockly.FieldDropdown(mixbot_display_rotate.OPERATORS), 'OP'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + }, + OPERATORS: [ + [Blockly.Msg.mixpy_PL_PIE_SHADOW_N, '0'], + [Blockly.Msg.CLOCKWISE + '90' + Blockly.Msg.blockpy_setheading_degree, '1'], + [Blockly.Msg.CLOCKWISE + '180' + Blockly.Msg.blockpy_setheading_degree, '2'], + [Blockly.Msg.CLOCKWISE + '270' + Blockly.Msg.blockpy_setheading_degree, '3'] + ] +}; + +/** + * @deprecated To be removed in the future + */ +export const bitbot_display_image_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + for (let i = 0; i < 12; i++) { + let dummyInputObj = this.appendDummyInput(); + for (let j = 0; j < 12; j++) { + dummyInputObj.appendField(new Blockly.FieldColour('#000', null, { + colourOptions: ['#f00', '#000'], + columns: 2 + }), i + '-' + j); + } + } + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +export const bitbot_display_bitmap_create = { + init: function () { + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_CREATE_IMAGE) + this.appendDummyInput('') + .setAlign(Blockly.inputs.Align.CENTRE) + .appendField(new Blockly.FieldBitmap(bitbot_display_bitmap_create.BITMAP, null, { + filledColor: '#000', + emptyColor: '#5ba5a5', + bgColor: '#e5e7f1' + }), 'BITMAP'); + this.setOutput(true); + this.setColour(DISPLAY_ONBOARD_HUE); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Create_image1); + }, + BITMAP: Array.from({ length: 12 }, () => new Array(12).fill(0)) +}; + +export const onboard_tft_show_image_xy = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_NUMBER); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_show_image_xy_direct = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput("x") + .setCheck(Number) + .appendField(Blockly.Msg.OLED_BITMAP) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("direct") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_AipImageClassify_Image + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_show_image_or_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_DRAWSTR); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("space") + .setCheck(Number) + .appendField(Blockly.Msg.MICROPYTHON_DISPLAY_FONT_SPACE); + this.appendDummyInput("") + .appendField(Blockly.Msg.TEXT_CENTER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MICROPYTHON_DISPLAY_YES, "True"], + [Blockly.Msg.MICROPYTHON_DISPLAY_NO, "False"] + ]), 'center') + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SHOW_IMAGE_OR_STRING_DELAY); + } +}; + +export const onboard_tft_show_frame_string_delay = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_ESP32_MONITOR_SHOW_FRAME); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TURTLE_WRITE_FONT_NUM); + this.appendValueInput("time") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_SCROLL_INTERVAL); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_display_shape_rect = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "name": "shape", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_HOLLOW, 'rect'], + [Blockly.Msg.MPYTHON_DISPLAY_SOLID, 'fill_rect'] + ], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, + { + "name": "x", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y", + "type": "input_value", + //"check": "Number" + }, + { + "name": "w", + "type": "input_value", + //"check": "Number" + }, + { + "name": "h", + "type": "input_value", + //"check": "Number" + }, + { + "name": "VAR", + "type": "input_value", + //"check": "Number" + }, + { + "name": "boolean", + "type": "input_value", + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_DISPLAY_SHAPE_RECT_TOOLTIP, + "message0": Blockly.Msg.ONBOARD_TFT_DISPLAY_SHAPE_RECT_MESSAGE0, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const onboard_tft_display_hvline = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "name": "dir_h_v", + "options": [ + [Blockly.Msg.mpython_vertical, '0'], + [Blockly.Msg.mpython_horizontal, '1'] + ], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, + { + "name": "x", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y", + "type": "input_value", + //"check": "Number" + }, + { + "name": "length", + "type": "input_value", + //"check": "Number" + }, + { + "name": "VAR", + "type": "input_value", + //"check": "Number" + }, + { + "name": "boolean", + "type": "input_value", + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.MPYTHON_DISPLAY_HVLINE_TOOLTIP, + "message0": Blockly.Msg.ONBOARD_TFT_DISPLAY_HVLINE_MESSAGE0, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const onboard_tft_display_line = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "type": "input_dummy" + }, { + "name": "x1", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y1", + "type": "input_value", + //"check": "Number" + }, + { + "name": "x2", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y2", + "type": "input_value", + //"check": "Number" + }, + { + "name": "VAR", + "type": "input_value", + //"check": "Number" + }, + { + "name": "boolean", + "type": "input_value", + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "tooltip": Blockly.Msg.mpython_display_line_TOOLTIP, + "message0": Blockly.Msg.onboard_mpython_display_line_MESSAGE0, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const onboard_tft_get_pixel = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_COLOUR); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_JS_MONITOR_BRIGHTNESS); + } +}; + +export const onboard_tft_bright_point = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('x') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_LCD_SETCOLOR) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_GET_POINT_X); + this.appendValueInput('y') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_MONITOR_PLOT_POINT_Y); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_DISPLAY_SETPIXEL); + } +}; + +export const onboard_tft_fill = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_SCREEN_FILL); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_clock_init = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_INIT_CLOCK); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CENTER_POS); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.OLED_CIRCLE_RADIUS); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_clock_get_rtctime = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.GET_RTCTIME); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_clock_set_time = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.SET_TIME); + this.appendValueInput("h") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_HOUR); + this.appendValueInput("m") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MINUTE); + this.appendValueInput("s") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_SECOND); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_clock_draw = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.DRAW_CLOCK); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_clock_clear = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('SUB') + this.appendDummyInput() + .appendField(Blockly.Msg.CLEAR_CLOCK); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_STM32_TFT_BACKGROUND_COLOR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_display_shape_circle = { + init: function () { + this.jsonInit({ + "colour": DISPLAY_ONBOARD_HUE, + "args0": [ + { + "name": "shape", + "options": [ + [Blockly.Msg.MPYTHON_DISPLAY_HOLLOW, 'False'], + [Blockly.Msg.MPYTHON_DISPLAY_SOLID, 'True'] + ], + "type": "field_dropdown" + }, + { + "type": "input_dummy" + }, + { + "name": "x", + "type": "input_value", + //"check": "Number" + }, + { + "name": "y", + "type": "input_value", + //"check": "Number" + }, + { + "name": "r", + "type": "input_value", + //"check": "Number" + }, + { + "name": "VAR", + "type": "input_value", + //"check": "Number" + }, + { + "name": "boolean", + "type": "input_value", + } + ], + "inputsInline": true, + "helpUrl": Blockly.Msg.mpython_HELPURL, + "message0": Blockly.Msg.ONBOARD_TFT_DISPLAY_SHAPE_CIRCLE_MESSAGE0, + "nextStatement": null, + "previousStatement": null + }); + } +}; + +export const draw_pointer = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.DRAW_POINTER) + .appendField(Blockly.Msg.DRAW_POINTER_ANGLE); + this.appendValueInput('angle'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DRAW_POINTER_DU); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.DRAW_POINTER_TOOLTIP); + } +}; + +export const nova_draw_pointer = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.DRAW_POINTER) + .appendField(Blockly.Msg.DRAW_POINTER_ANGLE); + this.appendValueInput('angle'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DRAW_POINTER_DU); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.DRAW_POINTER_TOOLTIP); + } +}; + +export const onboard_tft_show_texts = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_Display_long_text); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_NUMBER); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const onboard_tft_show_qrcode = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('direct') + .appendField(Blockly.Msg.OLED_BITMAP) + .appendField(Blockly.Msg.MIXLY_QR_CODE); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + + +export const onboard_tft_show_qrcode_details = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP) + .appendField(Blockly.Msg.MIXLY_QR_CODE); + this.appendValueInput("x") + .setCheck(Number) + .appendField('x'); + this.appendValueInput("y") + .setCheck(Number) + .appendField('y'); + this.appendValueInput("size") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_NUMBER); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ERROR_RATE) + .appendField(new Blockly.FieldDropdown([ + ["0", "7%"], + ["1", "15%"], + ["2", "25%"], + ["3", "30"] + ]), "correct"); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.HTML_COLOUR); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + this.appendValueInput('boolean') + .appendField(Blockly.Msg.MIXLY_synchronize); + } + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_show_image = { + init: function () { + this.setColour(DISPLAY_ONBOARD_HUE); + this.appendValueInput('data') + .appendField(Blockly.Msg.OLED_BITMAP); + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.OLED_BITMAP_OR_STRING); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_scroll_string = { + init: function () { + display_scroll_string.init.call(this); + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_show_frame_string = { + init: function () { + display_show_frame_string.init.call(this); + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_shift = { + init: function () { + display_shift.init.call(this); + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_get_screen_pixel = { + init: function () { + display_get_screen_pixel.init.call(this); + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_bright_screen = { + init: function () { + display_bright_screen.init.call(this); + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_clear = { + init: function () { + display_clear.init.call(this); + this.appendDummyInput() + .appendField(`(${Blockly.Msg.MIXLY_DEPRECATED})`); + this.setWarningText(Blockly.Msg.MIXLY_DEPRECATED_WARNING_TEXT); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/factory.js b/mixly/boards/default_src/micropython/blocks/factory.js new file mode 100644 index 00000000..e1b8f338 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/factory.js @@ -0,0 +1,285 @@ +import * as Blockly from 'blockly/core'; + +const FACTORY_HUE = "#777777"//65; + +export const factory_from_import = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField("from ") + .appendField(new Blockly.FieldTextInput('ESP32'), 'path') + .appendField(" import ") + .appendField(new Blockly.FieldTextInput('*'), 'module'); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const factory_import = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField("import ") + .appendField(new Blockly.FieldTextInput('module'), 'module'); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const factory_function_noreturn = { + init: function () { + //console.log('init'); + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('my_function'), 'NAME'); + this.itemCount_ = 1; + this.arguments_ = ['x'];//add + this.updateShape_(); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['factory_create_with_item'], this)); + }, + mutationToDom: function () { + //console.log('mutationToDom'); + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + //add + for (var i = 0; i < this.arguments_.length; i++) { + var parameter = document.createElement('arg'); + parameter.setAttribute('name', this.arguments_[i]); + container.appendChild(parameter); + } + return container; + }, + domToMutation: function (xmlElement) { + //console.log('domToMutation'); + this.arguments_ = [];//add + //add + for (var i = 0; xmlElement.childNodes[i]; i++) { + let childNode = xmlElement.childNodes[i]; + if (childNode.nodeName.toLowerCase() == 'arg') { + this.arguments_.push(childNode.getAttribute('name')); + } + } + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + decompose: function (workspace) { + //console.log('decompose'); + var containerBlock = + workspace.newBlock('factory_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK') + .connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('factory_create_with_item'); + itemBlock.initSvg(); + itemBlock.setFieldValue(this.arguments_[i], 'NAME');//add + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function (containerBlock) { + //console.log('compose'); + this.arguments_ = [];//add + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + this.arguments_.push(itemBlock.getFieldValue('NAME'));//add + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + saveConnections: function (containerBlock) { + //console.log('saveConnections'); + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + updateShape_: function () { + //console.log('updateShape_'); + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + for (var i = 0; i < this.itemCount_; i++) { + this.appendValueInput('ADD' + i) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(this.arguments_[i]); + } + } +}; + +export const factory_create_with_container = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.appendStatementInput('STACK'); + this.contextMenu = false; + } +}; + +export const factory_create_with_item = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE + ':') + .appendField(new Blockly.FieldTextInput('x'), 'NAME'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.contextMenu = false; + } +}; + +export const factory_function_return = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('my_function'), 'NAME'); + this.itemCount_ = 1; + this.arguments_ = ['x'];//add + this.updateShape_(); + this.setOutput(true); + this.setMutator(new Blockly.icons.MutatorIcon(['factory_create_with_item'], this)); + }, + mutationToDom: factory_function_noreturn.mutationToDom, + domToMutation: factory_function_noreturn.domToMutation, + decompose: factory_function_noreturn.decompose, + compose: factory_function_noreturn.compose, + saveConnections: factory_function_noreturn.saveConnections, + updateShape_: factory_function_noreturn.updateShape_ +}; + +export const factory_declare = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('test'), 'NAME') + .appendField("=") + .appendField(new Blockly.FieldTextInput('Test'), 'TYPE') + .appendField("()"); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const factory_callMethod_noreturn = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('test'), 'NAME') + .appendField('.') + .appendField(new Blockly.FieldTextInput('callMethod'), 'METHOD'); + this.itemCount_ = 1; + this.arguments_ = ['x'];//add + this.updateShape_(); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['factory_create_with_item'], this)); + }, + mutationToDom: factory_function_noreturn.mutationToDom, + domToMutation: factory_function_noreturn.domToMutation, + decompose: factory_function_noreturn.decompose, + compose: factory_function_noreturn.compose, + saveConnections: factory_function_noreturn.saveConnections, + updateShape_: factory_function_noreturn.updateShape_ +}; + +export const factory_callMethod_return = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('test'), 'NAME') + .appendField('.') + .appendField(new Blockly.FieldTextInput('callMethod'), 'METHOD'); + this.itemCount_ = 1; + this.arguments_ = ['x'];//add + this.updateShape_(); + this.setOutput(true); + this.setMutator(new Blockly.icons.MutatorIcon(['factory_create_with_item'], this)); + }, + mutationToDom: factory_function_noreturn.mutationToDom, + domToMutation: factory_function_noreturn.domToMutation, + decompose: factory_function_noreturn.decompose, + compose: factory_function_noreturn.compose, + saveConnections: factory_function_noreturn.saveConnections, + updateShape_: factory_function_noreturn.updateShape_ +}; + +export const factory_block = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('display.scroll("Hello World!")'), 'VALUE'); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const factory_block_return = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('test'), 'VALUE'); + this.setOutput(true); + } +}; + +export const factory_block_with_textarea = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldMultilineInput('display.scroll("Hello World!")\ndisplay.scroll("Hello Mixly!")'), 'VALUE'); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const factory_block_return_with_textarea = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldMultilineInput('Hello\nMixly'), 'VALUE'); + this.setOutput(true); + } +}; + +export const folding_block = { + init: function () { + this.setColour(FACTORY_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(Blockly.Msg.FOLDING_BLOCK), "peien"); + this.appendStatementInput('DO') + .appendField(''); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.FOLDING_BLOCK_HELP); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/inout.js b/mixly/boards/default_src/micropython/blocks/inout.js new file mode 100644 index 00000000..36da13a8 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/inout.js @@ -0,0 +1,362 @@ +import * as Blockly from 'blockly/core'; + +const BASE_HUE = 20//'#ae3838';//40; + +export const inout_highlow = { + init: function () { + this.setColour(BASE_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_HIGH, "HIGH"], [Blockly.Msg.MIXLY_LOW, "LOW"]]), 'BOOL') + this.setOutput(true, Boolean); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_HIGHLOW_TOOLTIP); + } +}; + +export const inout_digital_write = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_Digital_PINMODEOUT) + .setCheck(Number); + this.appendValueInput("STAT") + .appendField(Blockly.Msg.MIXLY_STAT) + .setCheck([Number, Boolean]); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_DIGITAL_WRITE_TOOLTIP); + } +}; + +export const inout_digital_read = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.MIXLY_Digital_PINMODEIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MACHINE_VALUE) + this.setInputsInline(true); + this.setOutput(true, [Boolean, Number]); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_DIGITAL_READ_TOOLTIP); + } +}; + +export const inout_pwm_analog_write = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField("PWM" + Blockly.Msg.MIXLY_Analog_PINMODEOUT) + .setCheck(Number); + this.appendValueInput("NUM", Number) + .appendField(Blockly.Msg.MIXLY_VALUE2) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_PWM_ANALOG_WRITE_TOOLTIP); + } +}; + +export const inout_analog_write = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField("DAC" + Blockly.Msg.MIXLY_Analog_PINMODEOUT) + .setCheck(Number); + this.appendValueInput("NUM", Number) + .appendField(Blockly.Msg.MIXLY_VALUE2) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_ANALOG_WRITE_TOOLTIP); + } +}; + +export const inout_analog_write_set = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_Analog_PINMODEOUT) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_PERIOD_MIL) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_mSecond, "period"], + [Blockly.Msg.MIXLY_uSecond, "period_microseconds"] + ]), "key"); + this.appendValueInput("NUM", Number) + .appendField(Blockly.Msg.MIXLY_STAT) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_ANALOG_WRITE_SET_TOOLTIP); + } +}; + +export const inout_pwm_analog_write_set_freq = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField("PWM" + Blockly.Msg.MIXLY_Analog_PINMODEOUT) + .setCheck(Number); + this.appendValueInput("NUM", Number) + .appendField(Blockly.Msg.MIXLY_FREQUENCY + Blockly.Msg.MIXLY_STAT) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_PWM_ANALOG_WRITE_SET_FREQ_TOOLTIP); + } +}; + +export const inout_analog_read = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.MIXLY_Analog_PINMODEIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MACHINE_VALUE) + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_ANALOG_READ_TOOLTIP); + } +}; + +export const inout_analog_atten = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_Analog_PINMODEIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_REF_VOLTAGE + Blockly.Msg.MIXLY_STAT) + .appendField(new Blockly.FieldDropdown([ + ["3.3V", "machine.ADC.ATTN_11DB"], + ["2.2V", "machine.ADC.ATTN_6DB"], + ["1.5V", "machine.ADC.ATTN_2_5DB"], + ["1.2V", "machine.ADC.ATTN_0DB"] + ]), "atten"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_ANALOG_ATTEN_TOOLTIP); + } +}; + +export const inout_pin_pressed = { + init: function () { + this.setColour(BASE_HUE); + this.appendValueInput('pin') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR); + // this.appendDummyInput() + // .appendField(Blockly.Msg.MIXLY_IS_TOUCHED); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MACHINE_VALUE) + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_PIN_PRESSED_TOOLTIP); + } +}; + +export const inout_pin_attachInterrupt = { + init: function () { + this.setColour(20); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_ATTACHINTERRUPT_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RISING, "machine.Pin.IRQ_RISING"], + [Blockly.Msg.MIXLY_FALLING, "machine.Pin.IRQ_FALLING"], + [Blockly.Msg.MIXLY_CHANGE, "(machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING)"] + ]), "mode"); + this.appendValueInput('DO') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_PIN_ATTACHINTERRUPT_TOOLTIP); + } +}; + +export const inout_digital_init = { + init: function () { + this.setColour(20); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldTextInput('pin#'), 'PIN_OBJ'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_AS) + // .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE+Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_Digital_PINMODEOUT, "machine.Pin.OUT"], + [Blockly.Msg.MIXLY_Digital_PINMODEIN, "machine.Pin.IN"], + [Blockly.Msg.MIXLY_PINMODEPULLUP, "machine.Pin.IN, machine.Pin.PULL_UP"], + [Blockly.Msg.MIXLY_PINMODEPULLDOWN, "machine.Pin.IN, machine.Pin.PULL_DOWN"] + ]), "MODE") + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_DIGITAL_INIT_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('PIN_OBJ') == 'pin#' ? null : this.getFieldValue('PIN_OBJ')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('PIN_OBJ'))) { + this.setTitleValue(newName, 'PIN_OBJ'); + } + } +}; + +export const inout_pwm_analog_write_init = { + init: function () { + this.setColour(BASE_HUE); + // this.appendValueInput("PIN", Number) + // .appendField(Blockly.Msg.MIXLY_SETUP) + // .appendField("PWM"+Blockly.Msg.MIXLY_Analog_PINMODEOUT) + // .appendField('pwm') + // .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldTextInput('pwm#'), 'PIN_OBJ') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_AS) + this.appendDummyInput("") + .appendField("PWM" + Blockly.Msg.MIXLY_Analog_PINMODEOUT) + // .appendField('pwm') + // .appendField(new Blockly.FieldDropdown(profile.default.pwm_pin),"PIN") + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_PWM_ANALOG_WRITE_INIT_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('PIN_OBJ') == 'pwm#' ? null : this.getFieldValue('PIN_OBJ')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('PIN_OBJ'))) { + this.setTitleValue(newName, 'PIN_OBJ'); + } + } +}; + +export const inout_analog_write_init = { + init: function () { + this.setColour(BASE_HUE); + // this.appendValueInput("PIN", Number) + // .appendField(Blockly.Msg.MIXLY_SETUP) + // .appendField("PWM"+Blockly.Msg.MIXLY_Analog_PINMODEOUT) + // .appendField('pwm') + // .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldTextInput('dac#'), 'PIN_OBJ') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_AS) + this.appendDummyInput("") + .appendField("DAC" + Blockly.Msg.MIXLY_Analog_PINMODEOUT) + // .appendField('dac') + // .appendField(new Blockly.FieldDropdown(profile.default.dac_pin),"PIN") + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_ANALOG_WRITE_INIT_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('PIN_OBJ') == 'dac#' ? null : this.getFieldValue('PIN_OBJ')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('PIN_OBJ'))) { + this.setTitleValue(newName, 'PIN_OBJ'); + } + } +}; + +export const inout_analog_read_init = { + init: function () { + this.setColour(BASE_HUE); + // this.appendValueInput("PIN", Number) + // .appendField(Blockly.Msg.MIXLY_SETUP) + // .appendField("PWM"+Blockly.Msg.MIXLY_Analog_PINMODEOUT) + // .appendField('pwm') + // .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldTextInput('adc#'), 'PIN_OBJ') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_AS) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_Analog_PINMODEIN) + // .appendField('adc') + // .appendField(new Blockly.FieldDropdown(profile.default.adc_pin),"PIN") + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_ANALOG_READ_INIT_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('PIN_OBJ') == 'adc#' ? null : this.getFieldValue('PIN_OBJ')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('PIN_OBJ'))) { + this.setTitleValue(newName, 'PIN_OBJ'); + } + } +}; + +export const inout_pin_pressed_init = { + init: function () { + this.setColour(BASE_HUE); + // this.appendValueInput("PIN", Number) + // .appendField(Blockly.Msg.MIXLY_SETUP) + // .appendField("PWM"+Blockly.Msg.MIXLY_Analog_PINMODEOUT) + // .appendField('pwm') + // .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldTextInput('tc#'), 'PIN_OBJ') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_AS) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR) + // .appendField('tc') + // .appendField(new Blockly.FieldDropdown(profile.default.tc_pin),"PIN") + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_INOUT_PIN_PRESSED_INIT_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('PIN_OBJ') == 'tc#' ? null : this.getFieldValue('PIN_OBJ')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('PIN_OBJ'))) { + this.setTitleValue(newName, 'PIN_OBJ'); + } + } +}; + +export const inout_pinMode = inout_digital_init; +export const inout_analog_write_set_freq = inout_pwm_analog_write_set_freq; +export const pin_pressed_init = inout_pin_pressed_init; +export const pin_pressed = inout_pin_pressed; +export const controls_pin_attachInterrupt = inout_pin_attachInterrupt; diff --git a/mixly/boards/default_src/micropython/blocks/iot.js b/mixly/boards/default_src/micropython/blocks/iot.js new file mode 100644 index 00000000..a1ab8ed9 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/iot.js @@ -0,0 +1,900 @@ +import * as Blockly from 'blockly/core'; +import * as Mixly from 'mixly'; + +const IOT_HUE = '#526FC3'; +//'#2FAD7A'; + +export const iot_wifi_connect = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_IOT_CONNECT_WIFI); + this.appendValueInput('WIFINAME') + .setCheck(String) + .appendField(Blockly.Msg.HTML_NAME); + this.appendValueInput('PASSWORD') + .setCheck(String) + .appendField(Blockly.Msg.HTML_PASSWORD); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_WIFI_CONNECT_TOOLTIP); + } +}; + +export const iot_onenet_connect = { + init: function () { + this.setColour(IOT_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("OneNET" + Blockly.Msg.TUPLE_JOIN); + this.appendValueInput('CLIENT') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_ONENET_CLIENT); + this.appendValueInput('SERVER') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_ONENET_SERVER); + this.appendValueInput('USERNAME') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_ONENET_USERNAME); + this.appendValueInput('PASSWORD') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_ONENET_PASSWORD); + this.appendValueInput('TOPIC') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_ESP32_ONENET_TOPIC); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_ESP32_ONENET_SUB); + //this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_CONNECT_TOOLTIP); + } +}; + +export const iot_onenet_disconnect = { + init: function () { + this.setColour(IOT_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("OneNET") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_DISCONNECT_ONENET); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_DISCONNECT_TOOLTIP); + } +}; + +export const iot_onenet_check = { + init: function () { + this.setColour(IOT_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("OneNET") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_CHECK_ONENET); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_CHECK_TOOLTIP); + } +}; + +export const iot_onenet_publish_dict = { + init: function () { + this.setColour(IOT_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("OneNET") + this.appendValueInput('DICT') + .appendField(Blockly.Msg.MIXLY_ESP32_PUBLISH_ONENET); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_PRINT_DATA) + .appendField(new Blockly.FieldCheckbox('TRUE'), 'is_print'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_PUBLISH_DICT_TOOLTIP); + } +}; + +export const iot_onenet_publish = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(IOT_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("OneNET") + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendDummyInput() + .appendField(new Blockly.FieldLabel(Blockly.Msg.MIXLY_ESP32_PUBLISH_ONENET), 'TIP') + .setAlign(Blockly.inputs.Align.RIGHT) + this.itemCount_ = 2; + this.updateShape_(); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['iot_publish_item'], this)); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_PUBLISH_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('iot_publish_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('iot_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + let i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (let i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } + var keyNames = []; + for (let i = 0; this.getInput('ADD' + i); i++) { + //this.getInput('VALUE' + i).removeField("KEY"+i); + keyNames.push(this.getFieldValue("KEY" + i)) + this.removeInput('ADD' + i); + } + // Rebuild block. + if (this.itemCount_ == 0) { + //this.getField('TIP') + //.setText(Blockly.Msg.MIXLY_ESP32_PUBLISH_ONENET_EMPTY); + this.setFieldValue(Blockly.Msg.MIXLY_ESP32_PUBLISH_ONENET_EMPTY, 'TIP'); + } else { + //this.getField('TIP') + //.setText(Blockly.Msg.MIXLY_ESP32_PUBLISH_ONENET); + this.setFieldValue(Blockly.Msg.MIXLY_ESP32_PUBLISH_ONENET, 'TIP'); + for (let i = 0; i < this.itemCount_; i++) { + this.appendValueInput('ADD' + i) + .setCheck(null) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField( + new Blockly.FieldTextInput( + keyNames.length > i + ? keyNames[i] + : '"key' + (i + 1) + '"'), + 'KEY' + i) + .appendField(":") + } + } + }, getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const iot_publish_container = { + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.DICTS_CREATE_WITH_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const iot_publish_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.DICTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.DICTS_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const iot_create_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.DICTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.DICTS_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const iot_mixio_connect = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CREATE_MQTT_CLIENT_AND_CONNECT); + this.appendValueInput('SERVER') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_EMQX_SERVER) + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendValueInput('USERNAME') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_WIFI_USERNAME) + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendValueInput('PASSWORD') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_IOT_PASSWORD) + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendValueInput('PROJECT') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_EMQX_PROJECT) + .setAlign(Blockly.inputs.Align.RIGHT) + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const IOT_MIXIO_PUBLISH = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("MixIO") + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_NEW) + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_TOPIC); + this.appendValueInput('MSG') + .appendField(Blockly.Msg.HTML_BODY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_PUBLISH_TOOLTIP); + } +}; + +export const IOT_MIXIO_PUBLISHEX = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("MixIO") + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_NEW) + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_TOPIC); + this.appendValueInput('MSG') + .appendField(Blockly.Msg.HTML_BODY); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_Service_quality_display) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_AT_MOST_ONCE,"0"], + [Blockly.Msg.MIXLY_AT_LEAST_ONCE,"1"] + ]),"quality") + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_PUBLISH_TOOLTIP); + } +}; + +export const IOT_MIXIO_SUBSCRIBE = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("MixIO") + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_EMQX_SUBSCRIBE + Blockly.Msg.MIXLY_MICROBIT_MSG) + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_TOPIC); + this.appendValueInput('METHOD') + .appendField(Blockly.Msg.MIXLY_EMQX_SET_METHOD); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_SUBSCRIBE_TOOLTIP); + } +}; + +export const iot_mixio_disconnect = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("MixIO") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_DISCONNECT_ONENET); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + // this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_DISCONNECT_TOOLTIP); + } +}; + +export const iot_mixio_connect_only = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("MixIO") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_EMQX_CONNECT); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + // this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_DISCONNECT_TOOLTIP); + } +}; + +export const iot_mixio_check = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("MixIO") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_CHECK_ONENET); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + // this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_ONENET_CHECK_TOOLTIP); + } +}; + +export const iot_mixio_format_topic = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_FORMAT) + .appendField(Blockly.Msg.MQTT_Topic); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const iot_mixio_format_msg = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_FORMAT) + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_MSG); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const IOT_FORMATTING = { + init: function () { + this.setColour(IOT_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_ESP32_IOT_MAP_FORMATING); + this.setOutput(true); + // this.setTooltip(); + } +}; + +export const IOT_FORMAT_STRING = { + init: function () { + this.setColour(IOT_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_FORMAT + '(Json)'); + this.setOutput(true); + // this.setTooltip(); + } +}; + +export const IOT_EMQX_PING = { + init: function () { + this.setColour(IOT_HUE); + // this.appendValueInput('VAR') + // .setCheck("var") + this.appendDummyInput() + .appendField("MixIO") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_EMQX_PING); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_PING_TOOLTIP); + } +}; + +export const IOT_MIXIO_NTP = { + init: function () { + this.setColour(IOT_HUE); + // this.appendValueInput('VAR') + // .setCheck("var") + this.appendDummyInput() + .appendField("MixIO") + .appendField(Blockly.Msg.MIXLY_GET_NTP) + this.appendValueInput('addr') + .appendField(Blockly.Msg.blynk_SERVER_ADD); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const IOT_EMQX_INIT_AND_CONNECT_BY_SHARE_CODE = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CREATE_MQTT_CLIENT_AND_CONNECT); + this.appendValueInput('SERVER') + .appendField(Blockly.Msg.MIXLY_EMQX_SERVER) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('KEY') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + Blockly.Msg.MIXLY_MIXIO_SHARE_KEY) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const IOT_EMQX_INIT_AND_CONNECT_BY_MIXLY_CODE = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CREATE_MQTT_CLIENT_AND_CONNECT); + this.appendValueInput('SERVER') + .appendField(Blockly.Msg.MIXLY_EMQX_SERVER) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('KEY') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "Mixly Key") + .setAlign(Blockly.inputs.Align.RIGHT); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const iot_mixly_key = { + init: function () { + this.VISITOR_ID = Mixly.Config.BOARD.visitorId.str32.substring(0, 8).toUpperCase(); + this.setColour(IOT_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput(this.visitorId), 'VISITOR_ID'); + this.setOutput(true, null); + }, + onchange: function () { + const nowVisitorId = this.getFieldValue('VISITOR_ID'); + if (this.VISITOR_ID !== nowVisitorId) + this.setFieldValue(this.VISITOR_ID, 'VISITOR_ID'); + } +}; + +export const iot_client_onboard = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField('MixIO') + .appendField(Blockly.Msg.MSG.catEthernet_clinet); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const iot_http_client = { + init: function () { + this.setColour(IOT_HUE); + // this.appendValueInput('VAR') + // .setCheck("var") + this.appendDummyInput() + .appendField("HTTP" + Blockly.Msg.MIXLY_Client) + this.appendValueInput('addr') + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_REQUESTS_GET) + .appendField(Blockly.Msg.MIXLY_GET_CURRENT_TIME) + .appendField(Blockly.Msg.MIXLY_OPEN_DEBUG) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_TRUE, "True"], + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_FALSE, "False"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const iot_http_data = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("HTTP" + Blockly.Msg.MIXLY_Client) + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_REQUESTS_LEN, "client_len"], + [Blockly.Msg.MIXLY_REQUESTS_GET_LEN, "server_len"], + [Blockly.Msg.MIXLY_REQUESTS_MESSAGE, "text"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + + } +}; + +export const iot_mqtt_client = { + init: function () { + this.setColour(IOT_HUE); + // this.appendValueInput('VAR') + // .setCheck("var") + this.appendDummyInput() + .appendField("MQTT" + Blockly.Msg.MIXLY_Client) + this.appendValueInput('addr') + .appendField(Blockly.Msg.MIXLY_CONNECTTO); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_INIT_SUBSCRIBE) + .appendField(Blockly.Msg.MQTT_Topic) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GET_CURRENT_TIME, ""], + ]), "key") + .appendField(Blockly.Msg.MIXLY_OPEN_DEBUG) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_TRUE, "True"], + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_FALSE, "False"] + ]), "key2"); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const iot_mqtt_data = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField("MQTT" + Blockly.Msg.MIXLY_Client) + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_REQUESTS_LEN, "client_len"], + [Blockly.Msg.MIXLY_REQUESTS_GET_LEN, "server_len"], + [Blockly.Msg.MIXLY_REQUESTS_MESSAGE, "time_msg()"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + + } +}; + +export const iot_wificonnect = iot_wifi_connect; +export const iot_onenetconnect = iot_onenet_connect; +export const iot_onenetdisconnect = iot_onenet_disconnect; +export const iot_checkonenet = iot_onenet_check; +export const iot_publish = iot_onenet_publish; + +export const iot_connect_ollama = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CONNECT_OLLAMA); + this.appendValueInput('SERVER') + .appendField(Blockly.Msg.MIXLY_EMQX_SERVER) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('NAME') + .appendField(Blockly.Msg.MODEL_NAME) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('NUMBER') + .appendField(Blockly.Msg.MIXLY_SET_MAXIMUM_HISTORICAL_SESSIONS_NUM); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const IOT_CONNECT_OLLAMA = iot_connect_ollama; + +export const iot_connect_openai = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CONNECT_OPENAI); + this.appendValueInput('SERVER') + .appendField(Blockly.Msg.MIXLY_EMQX_SERVER) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('KEY') + .appendField(Blockly.Msg.MIXLY_API_PRIVATE_KEY) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('NAME') + .appendField(Blockly.Msg.MODEL_NAME) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput('NUMBER') + .appendField(Blockly.Msg.MIXLY_SET_MAXIMUM_HISTORICAL_SESSIONS_NUM); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const use_ollama_llm_to_chat = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LLM_CHAT); + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_SEND); + this.appendValueInput('METHOD') + .appendField(Blockly.Msg.MIXLY_LLM_CONTENT_CALLBACK); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const use_ollama_llm_to_chat_return = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LLM_CHAT); + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_MIXGO_ESPNOW_SEND); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_REQUESTS_GET_RESULT) + this.setInputsInline(true); + this.setOutput(true); + } +}; + +// export const ollama_set_timeout = { +// init: function () { +// this.setColour(IOT_HUE); +// this.appendValueInput("VAR") +// .appendField('Ollama ' + Blockly.Msg.MIXLY_OLLAMA_SET_TIMEOUT); +// this.setInputsInline(true); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// } +// } + +// export const ollama_set_max_retries = { +// init: function () { +// this.setColour(IOT_HUE); +// this.appendValueInput("VAR") +// .appendField('Ollama ' + Blockly.Msg.MIXLY_OLLAMA_SET_MAX_RETRIES); +// this.setInputsInline(true); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// } +// } + +// export const ollama_set_custom_url = { +// init: function () { +// this.setColour(IOT_HUE); +// this.appendValueInput("TEXT") +// .appendField('Ollama ' + Blockly.Msg.MIXLY_OLLAMA_SET_CUSTOM_URL); +// this.setInputsInline(true); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// } +// } + +// export const ollama_select_model = { +// init: function () { +// this.setColour(IOT_HUE); +// this.appendValueInput("TEXT") +// .appendField('Ollama ' + Blockly.Msg.MIXLY_SELECT_MODEL); +// this.setInputsInline(true); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// } +// } + +// export const ollama_clear_user_history = { +// init: function () { +// this.setColour(IOT_HUE); +// this.appendDummyInput() +// .appendField('Ollama ' + Blockly.Msg.MIXLY_CLEAR_USER_HISTORY); +// this.setInputsInline(true); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// } +// } + +export const ollama_empty_history = { + init: function () { + this.setColour(IOT_HUE); + this.appendDummyInput() + .appendField('Ollama ' + Blockly.Msg.MIXLY_EMPTY_HISTORY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +const TINY_WEB_DB = 0; + +export const iot_tiny_web_db_init = { + init: function () { + this.setColour(TINY_WEB_DB); + this.appendDummyInput() + .appendField(`${Blockly.Msg.MIXLY_SETUP} TinyWebDB`); + this.appendValueInput('ADDR') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_EMQX_SERVER); + this.appendValueInput('USERNAME') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_EMQX_USERNAME); + this.appendValueInput('PASSWORD') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_IOT_PASSWORD); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const iot_tiny_web_db_init_with_mqtt = { + init: function () { + this.setColour(TINY_WEB_DB); + this.appendDummyInput() + .appendField(`${Blockly.Msg.MIXLY_SETUP} TinyWebDB`); + this.appendValueInput('MQTT') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(`MixIO ${Blockly.Msg.MIXLY_Client}`); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const iot_tiny_web_db_update = { + init: function () { + this.setColour(TINY_WEB_DB); + this.appendDummyInput() + .appendField('TinyWebDB'); + this.appendValueInput('TAG') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_UPDATE_VARIABLE); + this.appendValueInput('VALUE') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.DICTS_ADD_VALUE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const iot_tiny_web_db_get = { + init: function () { + this.setColour(TINY_WEB_DB); + this.appendDummyInput() + .appendField('TinyWebDB'); + this.appendValueInput('TAG') + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_GET_VARIABLE); + this.appendDummyInput() + .appendField(Blockly.Msg.DICTS_ADD_VALUE); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const iot_tiny_web_db_count = { + init: function () { + this.setColour(TINY_WEB_DB); + this.appendDummyInput() + .appendField('TinyWebDB'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_GET_VARIABLES_NUM); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const iot_tiny_web_db_search = { + init: function () { + this.setColour(TINY_WEB_DB); + this.appendDummyInput() + .appendField('TinyWebDB') + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_SEARCH_VARIABLES); + this.appendValueInput('NO') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_START_NUMBER); + this.appendValueInput('COUNT') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_VARIABLE_NUMBER); + this.appendValueInput('TAG') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_SEARCH_VARS); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TINY_WEB_DB_GET_VARIABLES_ALL, 'both'], + [Blockly.Msg.MIXLY_TINY_WEB_DB_GET_VARIABLES_TAG, 'tag'], + [Blockly.Msg.MIXLY_TINY_WEB_DB_GET_VARIABLES_VALUE, 'value'] + ]), 'DTYPE'); + this.setInputsInline(false); + this.setOutput(true); + } +}; + +export const iot_tiny_web_db_delete = { + init: function () { + this.setColour(TINY_WEB_DB); + this.appendDummyInput() + .appendField('TinyWebDB'); + this.appendValueInput('TAG') + .appendField(Blockly.Msg.MIXLY_TINY_WEB_DB_DELETE_VARIABLE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/network.js b/mixly/boards/default_src/micropython/blocks/network.js new file mode 100644 index 00000000..1695ce42 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/network.js @@ -0,0 +1,696 @@ +import * as Blockly from 'blockly/core'; + +const NETWORK_HUE = 225; + +export const network_init = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_NETWORK_INIT) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_NETWORK_MODE) + .appendField(new Blockly.FieldDropdown([ + ['STA', "STA"], + ['AP', "AP"] + ]), "mode"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_INIT_TOOLTIP); + } +}; + +export const network_open = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_NETWORK_WIFI_OPEN, "True"], + [Blockly.Msg.MIXLY_NETWORK_WIFI_CLOSE, "False"] + ]), "op"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_NETWORK_WIFI_FLAG) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('op'); + var mode0 = Blockly.Msg.MIXLY_ESP32_NETWORK_OPEN_TOOLTIP; + var TOOLTIPS = { + 'True': Blockly.Msg.MIXLY_NETWORK_WIFI_OPEN, + 'False': Blockly.Msg.MIXLY_NETWORK_WIFI_CLOSE, + }; + return TOOLTIPS[mode] + mode0 + }); + } +}; + +export const network_is_active = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_NETWORK_WIFI_IS_ACTIVE) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_NETWORK_WIFI_IS_ACTIVE); + } +}; + +export const network_scan = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_NETWORK_WIFI_SCAN) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(function () { + var mode = 'all'; + var mode0 = Blockly.Msg.MIXLY_ESP32_NETWORK_SCAN_TOOLTIP + var TOOLTIPS = { + '0': "ssid", + '1': 'bssid', + '2': "channel", + '3': "RSSI", + '4': "authmode", + '5': "hidden", + 'all': Blockly.Msg.MIXLY_NETWORK_WIFI_SCAN_ATTRIBUTE, + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const network_connect = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_NETWORK_CONNECT); + this.appendValueInput('id') + .setCheck(String) + .appendField(Blockly.Msg.HTML_NAME); + this.appendValueInput('password') + .setCheck(String) + .appendField(Blockly.Msg.HTML_PASSWORD); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_CONNECT_TOOLTIP); + } +}; + +export const network_wifi_connect = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_NETWORK_WIFI_CONNECT + Blockly.Msg.MIXLY_SYMBOL_QUESTION); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_WIFI_CONNECT_TOOLTIP); + } +}; + +export const network_get_connect = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_NETWORK_GET_WIFI); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_NETWORK_IP, "0"], + [Blockly.Msg.MIXLY_ESP32_NETWORK_MASK, "1"], + [Blockly.Msg.MIXLY_ESP32_NETWORK_GATEWAY, "2"], + ["DNS", "3"] + ]), "mode"); + this.setOutput(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('mode'); + var mode0 = Blockly.Msg.MIXLY_ESP32_NETWORK_GET_WIFI_TOOLTIP + var TOOLTIPS = { + '0': Blockly.Msg.MIXLY_ESP32_NETWORK_IP, + '1': Blockly.Msg.MIXLY_ESP32_NETWORK_MASK, + '2': Blockly.Msg.MIXLY_ESP32_NETWORK_GATEWAY, + '3': "DNS", + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const network_stop = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_NETWORK_STOP_CONNECT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_STOP_TOOLTIP); + } +}; + +export const network_get_wifi = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_NETWORK_GET_WIFI); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_NETWORK_WIFI_ESSID, "essid"], + [Blockly.Msg.MIXLY_NETWORK_WIFI_CHANNEL, "channel"] + ]), "op"); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_GET_WIFI_TOOLTIP); + } +}; + +export const network_ap_connect = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_HOTSPOT); + this.appendValueInput('essid') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_NAME); + this.appendValueInput('password') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_EMQX_PASSWORD); + this.appendValueInput('channel') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_NETWORK_WIFI_CHANNEL); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_AP_CONNECT_TOOLTIP); + } +}; + +export const network_server = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_NETWORK_SERVER1); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_NETWORK_SERVER2); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_CLOSE_TOOLTIP); + } +}; + +export const network_socket_init = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_INIT) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_TYPE) + .appendField(new Blockly.FieldDropdown([ + ['TCP', "TCP"], + ['UDP', "UDP"] + ]), "mode"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('mode'); + var mode0 = Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_INIT_TOOLTIP + var TOOLTIPS = { + 'TCP': 'TCP', + 'UDP': 'UDP', + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const network_socket_bind = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_LET_SOCKET) + this.appendValueInput('address') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_BIND_TO_ADDRESS); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_BIND_TOOLTIP); + } +}; + +export const network_socket_connect = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_LET_SOCKET) + this.appendValueInput('address') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_CONNECT_TO_ADDRESS); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_CONNECT_TOOLTIP); + } +}; + +export const network_socket_listen = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendValueInput('queue') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_LISTEN) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_QUEUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_LISTEN_TOOLTIP); + } +}; + +export const network_socket_accept = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_ACCEPT); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_ACCEPT_TOOLTIP); + } +}; + +export const network_socket_readline = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck('var'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_READLINE); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_READLINE_TOOLTIP); + } +}; + +export const network_socket_receive = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("TCP") + this.appendValueInput('size') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_RECEIVE) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_RECEIVE_TOOLTIP); + } +}; + +export const network_socket_send = { + init: function () { + this.setColour(NETWORK_HUE); + // .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + this.appendValueInput('VAR') + .setCheck("var") + .appendField("TCP") + this.appendValueInput('content') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_SEND) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_SEND_TOOLTIP); + } +}; + +export const network_socket_receive_from = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + .appendField("UDP") + this.appendValueInput('size') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_RECEIVE) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_RECEIVE_FROM_TOOLTIP); + } +}; + +export const network_socket_send_to = { + init: function () { + this.setColour(NETWORK_HUE); + // .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + this.appendValueInput('VAR') + .setCheck("var") + .appendField("UDP") + this.appendValueInput('content') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_SEND) + this.appendValueInput('address') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_TO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_SEND_TO_TOOLTIP); + } +}; + +export const network_socket_close = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput('VAR') + .setCheck("var") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_CLOSE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_NETWORK_SOCKET_CLOSE_TOOLTIP); + } +}; + + +export const requests_get = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendValueInput("DOMAIN") + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .setCheck(String); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_REQUESTS_GET) + .appendField(new Blockly.FieldTextInput('response'), 'VAR') + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.blockpy_REQUESTS_GET_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const requests_attribute = { + init: function () { + this.appendValueInput('VAL') + this.setColour(NETWORK_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown(requests_attribute.ATTR), 'ATTR') + this.setInputsInline(true); + this.setOutput(true, String); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('DIR'); + var TOOLTIPS = { + 'clear': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_CLEAR, + 'reset': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_RESET, + 'home': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_HOME + }; + return TOOLTIPS[mode]; + }); + }, + ATTR: [ + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_STATUS_CODE, 'status_code'], + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_TEXT, 'text'], + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_COOKIES, 'cookies'], + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_CONTENT, 'content'] + ] +}; + +export const requests_method = { + init: function () { + this.appendValueInput("VAR") + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .setCheck(String); + this.setColour(NETWORK_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_CONDUCT) + .appendField(new Blockly.FieldDropdown(requests_method.METHOD), 'DIR') + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_REQUESTS) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('DIR'); + var TOOLTIPS = { + 'forward': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_FORWARD, + 'backward': Blockly.Msg.MIXLY_TOOLTIP_TURTEL_BACKWARD + }; + return TOOLTIPS[mode]; + }); + }, + METHOD: [ + ['post', 'post'], ['put', 'put'], + ['delete', 'delete'], ['head', 'head'], + ['option', 'option'] + ] +}; + +export const ntptime_time = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET_NTP + '(NTP)') + this.appendValueInput("data") + .appendField(Blockly.Msg.blynk_SERVER_ADD) + this.setOutput(true, 'Tuple'); + this.setInputsInline(true); + } +}; + +export const ntptime_address = { + init: function () { + this.setColour(NETWORK_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ['ntp.aliyun.com', "ntp.aliyun.com"], + ['ntp1.aliyun.com', "ntp1.aliyun.com"], + ['ntp2.aliyun.com', "ntp2.aliyun.com"], + ['ntp3.aliyun.com', "ntp3.aliyun.com"], + ['ntp4.aliyun.com', "ntp4.aliyun.com"], + ['ntp5.aliyun.com', "ntp5.aliyun.com"], + ['ntp6.aliyun.com', "ntp6.aliyun.com"], + ['ntp7.aliyun.com', "ntp7.aliyun.com"], + ['time1.cloud.tencent.com', "time1.cloud.tencent.com"], + ['time2.cloud.tencent.com', "time2.cloud.tencent.com"], + ['time3.cloud.tencent.com', "time3.cloud.tencent.com"], + ['time4.cloud.tencent.com', "time4.cloud.tencent.com"], + ['time5.cloud.tencent.com', "time5.cloud.tencent.com"] + ]), 'op') + this.setOutput(true); + } +}; + +const COMMUNICATE_HUE = '#3288dd'; + +export const requests_get2 = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput("URL") + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .setCheck(String); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_CONDUCT) + .appendField(new Blockly.FieldDropdown([ + ["get", "get"], + ["head", "head"], + ["delete", "delete"] + ]), 'TYPE') + .appendField(Blockly.Msg.blockpy_REQUESTS) + .appendField(Blockly.Msg.MIXPY_REQUESTS_GET_RESULT) + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(""); + }, +}; + +export const requests_post = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput("URL") + .appendField(Blockly.Msg.DISPLAY_IMAGE_LET2) + .setCheck(String); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_CONDUCT) + .appendField(new Blockly.FieldDropdown([ + ["post", "post"], + ["put", "put"], + ["patch", "patch"] + ]), 'TYPE') + .appendField(Blockly.Msg.blockpy_REQUESTS) + this.appendValueInput("data") + .appendField(Blockly.Msg.blockpy_REQUESTS + Blockly.Msg.OLED_STRING) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXPY_REQUESTS_GET_RESULT) + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(""); + }, +}; + +export const requests_attribute2 = { + init: function () { + this.appendValueInput('VAL') + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown(requests_attribute2.ATTR), 'ATTR') + this.setInputsInline(true); + this.setOutput(true, String); + }, + ATTR: [ + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_TEXT, 'text'], + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_JSON, 'json()'], + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_STATUS_CODE, 'status_code'], + [Blockly.Msg.blockpy_REQUESTS_GET_ATTR_CONTENT, 'content'], + [Blockly.Msg.MIXPY_TEXT_ENCODE, 'encoding'] + ] +}; + +//educore_networke +export const educore_wifi_connect = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_IOT_CONNECT_WIFI); + this.appendValueInput('WIFINAME') + .setCheck(String) + .appendField(Blockly.Msg.HTML_NAME); + this.appendValueInput('PASSWORD') + .setCheck(String) + .appendField(Blockly.Msg.HTML_PASSWORD); + this.appendValueInput('TIMEOUT') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_IR_TIMEOUT); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MILLIS) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_IOT_WIFI_CONNECT_TOOLTIP); + } +}; + +export const educore_mqtt_connect = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_IOT_EMQX_CONNECT_TOOLTIP); + this.appendValueInput('SERVER') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_EMQX_SERVER) + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendValueInput('PORT') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_EMQX_PORT) + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendValueInput('CLIENT_ID') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_EMQX_CLIENT_ID) + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendValueInput('USERNAME') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_WIFI_USERNAME) + .setAlign(Blockly.inputs.Align.RIGHT) + this.appendValueInput('PASSWORD') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_IOT_PASSWORD) + .setAlign(Blockly.inputs.Align.RIGHT) + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const educore_mqtt_subscribe_message = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_EMQX_SUBSCRIBE + Blockly.Msg.MIXLY_MICROBIT_MSG) + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_TOPIC); + this.appendValueInput('MESSAGE') + .appendField(Blockly.Msg.blockpy_set_of); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_mqtt_topic_subscribe = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField("mqtt") + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_EMQX_SUBSCRIBE + Blockly.Msg.MIXLY_MICROBIT_MSG) + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_TOPIC); + this.appendValueInput('METHOD') + .appendField(Blockly.Msg.MIXLY_EMQX_SET_METHOD); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const educore_mqtt_topic_publish = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField("mqtt") + this.appendValueInput('TOPIC') + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_NEW) + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH_TOPIC); + this.appendValueInput('MSG') + .appendField(Blockly.Msg.HTML_BODY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const educore_mqtt_connect_success = { + init: function () { + this.setColour(COMMUNICATE_HUE); + this.appendDummyInput() + .appendField("mqtt" + Blockly.Msg.MIXLY_EMQX_IS_CONNECT) + this.setInputsInline(true); + this.setOutput(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/nova_g1.js b/mixly/boards/default_src/micropython/blocks/nova_g1.js new file mode 100644 index 00000000..13ef181b --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/nova_g1.js @@ -0,0 +1,84 @@ +import * as Blockly from 'blockly/core'; +import * as Mixly from 'mixly'; + +const NOVAG1_HUE = 100; + +export const get_potential_num = { + init: function () { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2]; + if (version == "mixgo_nova") { var name = 'Nova G1' } + this.setColour(NOVAG1_HUE); + this.appendDummyInput() + .appendField(name) + .appendField(Blockly.Msg.MIXLY_MIXGO_NOVA_POTENTIAL_NUM); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const nova_g1_motor = { + init: function () { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2]; + if (version == "mixgo_nova") { var name = 'Nova G1' } + this.setColour(NOVAG1_HUE); + this.appendValueInput('PIN') + .appendField(name) + .appendField(Blockly.Msg.MOTOR_DC) + .appendField(Blockly.Msg.LCD_NUMBERING) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, "CW"], + [Blockly.Msg.ANTI_CLOCKWISE, "CCW"], + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const nova_g1_usb = { + init: function () { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2]; + if (version == "mixgo_nova") { var name = 'Nova G1' } + this.setColour(NOVAG1_HUE); + this.appendValueInput('PIN') + .appendField(name) + .appendField(Blockly.Msg.SET_USB); + this.appendValueInput('percent') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_POWER_SUPPLY); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const nova_g1_spk_en = { + init: function () { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2]; + if (version == "mixgo_nova") { var name = 'Nova G1' } + this.setColour(NOVAG1_HUE); + this.appendDummyInput() + .appendField(name) + .appendField(Blockly.Msg.MIXLY_SPK_STATE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ON, "True"], + [Blockly.Msg.MIXLY_OFF, "False"] + ]), "state"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/pe_g1.js b/mixly/boards/default_src/micropython/blocks/pe_g1.js new file mode 100644 index 00000000..5336d8cd --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/pe_g1.js @@ -0,0 +1,156 @@ +import * as Blockly from 'blockly/core'; + +const PEG1_HUE = 100; + +export const pe_g1_use_i2c_init = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField('PE GX'); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const pe_g1_battery_left = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('SUB') + .appendField('PE GX') + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_CAR_BATTERY_LEFT); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const pe_g1_dc_motor = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('SUB') + .appendField('PE GX') + .setCheck("var"); + this.appendValueInput('PIN') + .appendField(Blockly.Msg.MOTOR_DC) + .appendField(Blockly.Msg.LCD_NUMBERING) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Direction) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE, "CW"], + [Blockly.Msg.ANTI_CLOCKWISE, "CCW"], + [Blockly.Msg.MOTOR_P, "P"], + [Blockly.Msg.MOTOR_N, "N"] + ]), "direction"); + this.appendValueInput('speed') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEPPER_SET_SPEED); + this.appendDummyInput("") + .appendField("%") + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const pe_g1_dc_motor_speed = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('SUB') + .appendField('PE GX') + .setCheck("var"); + this.appendValueInput('PIN') + .appendField(Blockly.Msg.MOTOR_DC) + .appendField(Blockly.Msg.LCD_NUMBERING) + + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_STEPPER_GET_SPEED); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const pe_g1_servo_set_angle = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('SUB') + .appendField('PE GX') + .setCheck("var"); + this.appendValueInput('PIN') + .appendField('180°' + Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.LCD_NUMBERING) + + this.appendValueInput("NUM", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SERVO_MOVE); + } +}; + +export const pe_g1_servo_set_speed = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('SUB') + .appendField('PE GX') + .setCheck("var"); + this.appendValueInput('PIN') + .appendField('360°' + Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.LCD_NUMBERING) + + this.appendValueInput("NUM", Number) + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_SPEED); + this.appendDummyInput() + .appendField('%'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SERVO_SPEED_TOOLIPS); + } +}; + +export const pe_g1_servo_get_angle = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('SUB') + .appendField('PE GX') + .setCheck("var"); + this.appendValueInput('PIN') + .appendField('180°' + Blockly.Msg.MIXLY_SERVO) + + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const pe_g1_servo_get_speed = { + init: function () { + this.setColour(PEG1_HUE); + this.appendValueInput('SUB') + .appendField('PE GX') + .setCheck("var"); + this.appendValueInput('PIN') + .appendField('360°' + Blockly.Msg.MIXLY_SERVO) + .appendField(Blockly.Msg.LCD_NUMBERING) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_SPEED); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/pins.js b/mixly/boards/default_src/micropython/blocks/pins.js new file mode 100644 index 00000000..8c120a3f --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/pins.js @@ -0,0 +1,337 @@ +import * as Blockly from 'blockly/core'; +import { Profile } from 'mixly'; + +const PINS_HUE = 230; + +export const pins_digital = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.digital), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_digital_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.digital_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_input_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.input_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_output_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.output_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pwm_input = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.pwm_input), 'PIN'); + this.setOutput(true); + } +}; + +export const analog_input = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.analog_input), 'PIN'); + this.setOutput(true); + } +}; + +export const pwm_output = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.pwm_output), 'PIN'); + this.setOutput(true); + } +}; + +export const analog_output = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.analog_output), 'PIN'); + this.setOutput(true); + } +}; + +export const espnow_channel = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.espnow_channel), 'PIN'); + this.setOutput(true, Number); + } +}; + + +export const i2c_A_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.i2c_A_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const i2c_B_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.i2c_B_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const spi_A_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.spi_A_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const spi_B_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.spi_B_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const spi_C_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.spi_C_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const spi_D_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.spi_D_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_analog = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.analog), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_analog_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.analog_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_dac = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.dac), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_dac_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.dac_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_button = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.button), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_pwm = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.pwm), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_pwm_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.pwm_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_touch_pin = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.touch_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_touch = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.touch), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_serial = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.serial_pin), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_builtinimg = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.builtinimg), 'PIN'); + this.setOutput(true, "esp32_image"); + } +}; + +export const pins_imglist = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.imglist), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_playlist = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.playlist), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_exlcdh = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.exlcdh), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_exlcdv = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.exlcdv), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_axis = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.axis), 'PIN'); + this.setOutput(true, Number); + } +}; +export const pins_brightness = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.brightness), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_tone_notes = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.tone_notes), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_radio_power = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.radio_power), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_radio_datarate = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.radio_datarate), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const pins_one_more = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.one_more), 'PIN'); + this.setOutput(true); + } +}; + +export const pins_digital_dot = { + init: function () { + this.setColour(PINS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.digital_dot), 'PIN'); + this.setOutput(true, Number); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/sensor.js b/mixly/boards/default_src/micropython/blocks/sensor.js new file mode 100644 index 00000000..7e980cac --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/sensor.js @@ -0,0 +1,910 @@ +import * as Blockly from 'blockly/core'; +import { sensor_LTR308 } from './sensor_onboard'; + +const SENSOR_HUE = 40; //'#9e77c9'//40; + +export const sensor_mixgo_button_is_pressed = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('btn') + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_PRESSED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_IS_PRESSED); + } +}; + +export const sensor_mixgo_button_was_pressed = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('btn') + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WAS_PRESSED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_WAS_PRESSED); + } +}; + +export const sensor_mixgo_button_get_presses = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('btn') + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_PRESSES); + this.appendValueInput('VAR') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_GET_PRESSES_TIME); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_BUTTON + Blockly.Msg.MIXLY_GET_PRESSES); + } +}; + +export const sensor_mixgo_button_attachInterrupt = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("btn") + .appendField(Blockly.Msg.MIXLY_ESP32_INTERRUPT) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RISING, "machine.Pin.IRQ_RISING"], + [Blockly.Msg.MIXLY_FALLING, "machine.Pin.IRQ_FALLING"], + [Blockly.Msg.MIXLY_CHANGE, "(machine.Pin.IRQ_RISING or machine.Pin.IRQ_FALLING)"] + ]), "mode"); + this.appendValueInput('DO') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_ATTACHINTERRUPT); + } +}; + +export const sensor_mixgo_extern_button_is_pressed = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_PRESSED); + this.appendValueInput("STAT") + .appendField(Blockly.Msg.MIXLY_ELECLEVEL); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_IS_PRESSED); + } +}; + +export const sensor_mixgo_extern_button_was_pressed = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WAS_PRESSED); + this.appendValueInput("STAT") + .appendField(Blockly.Msg.MIXLY_ELECLEVEL); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_WAS_PRESSED); + } +}; + +export const sensor_mixgo_extern_button_get_presses = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_PRESSES); + this.appendValueInput('VAR') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_GET_PRESSES_TIME); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_BUTTON + Blockly.Msg.MIXLY_GET_PRESSES); + } +}; + +export const sensor_mixgo_extern_button_attachInterrupt = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RISING, "machine.Pin.IRQ_RISING"], + [Blockly.Msg.MIXLY_FALLING, "machine.Pin.IRQ_FALLING"], + [Blockly.Msg.MIXLY_CHANGE, "(machine.Pin.IRQ_RISING or machine.Pin.IRQ_FALLING)"] + ]), "mode"); + this.appendValueInput('DO') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_ATTACHINTERRUPT); + } +}; + +export const sensor_mpu9250_attachGestureInterrupt = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_shake, "shake"], + [Blockly.Msg.MIXLY_UP, "up"], + [Blockly.Msg.MIXLY_DOWN, "down"], + [Blockly.Msg.MIXLY_LEFT, "left"], + [Blockly.Msg.MIXLY_RIGHT, "right"], + [Blockly.Msg.MIXLY_MICROBIT_face_up, "face up"], + [Blockly.Msg.MIXLY_MICROBIT_face_down, "face down"], + [Blockly.Msg.MIXLY_MICROBIT_freefall, "freefall"], + ["3g", "3g"], + ["6g", "6g"], + ["8g", "8g"] + ]), "gesture"); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('gesture'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT; + var mode1 = Blockly.Msg.MSG.catSensor; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_STATE; + var mode3 = Blockly.Msg.MIXLY_MICROBIT_PERFORMANCE + var TOOLTIPS = { + 'shake': Blockly.Msg.MIXLY_MICROBIT_shake, + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT, + 'face up': Blockly.Msg.MIXLY_MICROBIT_face_up, + 'face down': Blockly.Msg.MIXLY_MICROBIT_face_down, + 'freefall': Blockly.Msg.MIXLY_MICROBIT_freefall, + '3g': '3g', + '6g': '6g', + '8g': '8g' + }; + return mode0 + mode1 + mode2 + TOOLTIPS[mode] + mode3; + }); + } +}; + +export const sensor_mpu9250_gesture = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_shake, "shake"], + [Blockly.Msg.MIXLY_UP, "up"], + [Blockly.Msg.MIXLY_DOWN, "down"], + [Blockly.Msg.MIXLY_LEFT, "left"], + [Blockly.Msg.MIXLY_RIGHT, "right"], + [Blockly.Msg.MIXLY_MICROBIT_face_up, "face up"], + [Blockly.Msg.MIXLY_MICROBIT_face_down, "face down"] + ]), "gesture"); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('gesture'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT; + var mode1 = Blockly.Msg.MSG.catSensor; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_STATE; + var mode3 = Blockly.Msg.MIXLY_MICROBIT_PERFORMANCE + var TOOLTIPS = { + 'shake': Blockly.Msg.MIXLY_MICROBIT_shake, + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT, + 'face up': Blockly.Msg.MIXLY_MICROBIT_face_up, + 'face down': Blockly.Msg.MIXLY_MICROBIT_face_down, + // 'freefall':Blockly.Msg.MIXLY_MICROBIT_freefall, + // '3g': '3g', + // '6g': '6g', + // '8g': '8g' + }; + return mode0 + mode1 + mode2 + TOOLTIPS[mode] + mode3; + }); + } +}; + +export const sensor_mpu9250_get_acceleration = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION1; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_adxl345_get_acceleration = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_ADXL345) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION1; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_light_level = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_LIGHT_LEVEL) + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SENSOR_LIGHT_LEVEL_TOOLTIP); + } +}; + +export const sensor_mpu9250_calibrate_compass = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS); + } +}; + +// export const sensor_mpu9250_is_compass_calibrated = { +// init: function(){ +// this.setColour(SENSOR_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_IS_COMPASS_CALIBRATED) +// this.setOutput(true, Number); +// this.setInputsInline(true); +// this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_IS_COMPASS_CALIBRATED1); +// } +// }; +// export const sensor_mpu9250_compass_heading = { +// init: function(){ +// this.setColour(SENSOR_HUE); +// this.appendValueInput('SUB') +// .setCheck("var"); +// this.appendDummyInput() +// .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE) +// this.setOutput(true, Number); +// this.setInputsInline(true); +// } +// }; + +export const sensor_mpu9250_temperature = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE) + this.setOutput(true, Number); + this.setInputsInline(true); + + this.setTooltip(Blockly.Msg.MIXLY_GETTEMPERATUE); + } +}; + +export const sensor_mpu9250_field_strength = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET_COMPASS) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH, 'strength'], + [Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, 'heading'] + ]), 'compass'); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('compass'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_GET_COMPASS; + var TOOLTIPS = { + 'strength': Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH, + 'heading': Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + }; + return mode0 + TOOLTIPS[mode]; + }); + } +}; + +export const sensor_distance_hrsc04 = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CHAOSHENGBO) + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_CHAOSHENGBO); + } +}; + +//传感器-实时时钟块_获取时间 +export const RTC_get_time = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("RTC") + .setCheck("var"); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RTCGETTIME); + // this.appendDummyInput("").setAlign(Blockly.inputs.Align.RIGHT).appendField('myRTC'); + // this.appendDummyInput("").setAlign(Blockly.inputs.Align.RIGHT).appendField(new Blockly.FieldDropdown(RTC_TIME_TYPE), "TIME_TYPE"); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_RTC_GET_TIME_TOOLTIP); + // var thisBlock = this; + // this.setTooltip(function() { + // var mode = thisBlock.getFieldValue('TIME_TYPE'); + // var mode0 = Blockly.Msg.MIXLY_RTCGETTIME; + // var TOOLTIPS = { + // 'Year':Blockly.Msg.MIXLY_YEAR, + // 'Month':Blockly.Msg.MIXLY_MONTH, + // 'Day':Blockly.Msg.MIXLY_DAY, + // 'Hour':Blockly.Msg.MIXLY_HOUR, + // 'Minute':Blockly.Msg.MIXLY_MINUTE, + // 'Second':Blockly.Msg.MIXLY_SECOND, + // 'Week':Blockly.Msg.MIXLY_WEEK, + // 'Mix1':Blockly.Msg.MIXLY_MIX1, + // 'Mix2':Blockly.Msg.MIXLY_MIX2 + // }; + // return mode0 +TOOLTIPS[mode]; + // }); + } +}; + +export const RTC_set_time = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput("") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RTCSETTIME) + .appendField('myRTC'); + this.appendValueInput("hour") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_HOUR); + this.appendValueInput("minute") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_MINUTE); + this.appendValueInput("second") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_SECOND); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(false); + this.setTooltip(Blockly.Msg.MIXLY_RTCSETTIME + Blockly.Msg.MIXLY_MIX2); + } +}; + +export const RTC_set_date = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput("") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RTCSETDATE) + .appendField('myRTC'); + this.appendValueInput("year") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_YEAR); + this.appendValueInput("month") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_MONTH); + this.appendValueInput("day") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_DAY); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_RTCSETDATE + Blockly.Msg.MIXLY_MIX1); + } +}; + +export const sensor_compass_reset = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_COMPASS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Reset_COMPASS); + } +}; + +export const HCSR04 = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_CHAOSHENGBO); + this.appendValueInput("PIN1", Number) + .appendField('Trig #') + .setCheck(Number); + this.appendValueInput("PIN2", Number) + .appendField('Echo #') + .setCheck(Number); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_CHAOSHENGBO); + } + +}; + +export const sensor_dht11 = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("PIN", Number) + .appendField(new Blockly.FieldDropdown([ + ['DHT11', 'dht11'], + ['DHT22', 'dht22'] + //, ['DHT21', '21'], ['DHT33', '33'], ['DHT44', '44'] + ]), 'TYPE') + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(sensor_dht11.METHOD), "WHAT"); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('WHAT'); + var TOOLTIPS = { + 'temperature': Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_GET_TEM, + 'relative_humidity': Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_GET_HUM, + 'tempandhum': Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_GET_TEM_HUM + }; + return TOOLTIPS[op]; + }); + }, + METHOD: [ + [Blockly.Msg.MIXLY_GETTEMPERATUE, 'temperature'], + [Blockly.Msg.MIXLY_GETHUMIDITY, 'relative_humidity'], + [Blockly.Msg.MIXLY_DHT11_T_H, 'tempandhum'] + ] +}; + + +export const sensor_mixgo_extern_light = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_VALUE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ESP32_SENSOR_NIXGO_LIGHT_TOOLTIP); + } +}; + +export const sensor_mixgo_extern_sound = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_SOUND); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_VALUE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ESP32_SENSOR_NIXGO_SOUND_TOOLTIP); + } +}; + +export const number1 = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["1", "touch1"], + ["2", "touch2"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const sensor_mixgo_pin_pressed = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("button") + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_TOUCHED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_sensor_pin_pressed); + } +}; + +export const sensor_mixgo_extern_pin_near = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_NEAR); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_VALUE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP + Blockly.Msg.MIXLY_ESP32_NEAR); + } +}; + +export const sensor_mixgo_pin_near = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "left"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "right"] + ]), "direction") + .appendField(Blockly.Msg.MIXLY_ESP32_NEAR); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('direction'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + var TOOLTIPS = { + 'left': Blockly.Msg.TEXT_TRIM_LEFT, + 'right': Blockly.Msg.TEXT_TRIM_RIGHT, + }; + return mode0 + TOOLTIPS[mode] + mode1 + }); + } +}; + +export const RTC_set_datetime = { + init: function () { + this.setColour(SENSOR_HUE); + // this.appendDummyInput() + this.appendValueInput('SUB') + .appendField("RTC") + .appendField(Blockly.Msg.MIXLY_RTC_TIME) + .setCheck("var"); + this.appendValueInput('year') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_YEAR); + this.appendValueInput('month') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_MONTH); + this.appendValueInput('day') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_DAY); + this.appendValueInput('weekday') + .setCheck(Number) + .appendField(" " + + Blockly.Msg.MIXLY_WEEK2); + this.appendValueInput('hour') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_HOUR); + this.appendValueInput('minute') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_MINUTE); + this.appendValueInput('second') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_SECOND); + this.appendValueInput('millisecond') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_MILLISECOND); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_RTC_SET_DATATIME_TOOLTIP); + } +}; + +export const sensor_rtc_init = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput("") + .appendField("RTC") + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP) + .setCheck("var"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SENSOR_RTC_INT_TOOLTIP); + } +}; + +export const sensor_use_i2c_init = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + ["MPU9250", "MPU9250"], + ["BMP280", "BMP280"], + ["SHT20", "SHT20"], + ["ADXL345", "ADXL345"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setFieldValue("MPU9250", "key"); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_USE_I2C_TOOLTIP; + var TOOLTIPS = { + "MPU9250": "MPU9250", + "SHT20": "SHT20", + "BMP280": "BMP280", + "ADXL345": "ADXL345" + }; + return mode0 + TOOLTIPS[mode] + }); + } +}; + +export const sensor_bmp = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("BMP280") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETTEMPERATUE, "get_BMP_temperature()"], + [Blockly.Msg.MIXLY_GETPRESSURE, "get_BMP_pressure()"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "get_BMP_temperature()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_BMP_temperature_TOOLTIP, + "get_BMP_pressure()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_BMP_press_TOOLTIP, + }; + return TOOLTIPS[mode] + }); + } +}; + +export const sensor_sht = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("SHT20") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETTEMPERATUE, "get_SHT_temperature()"], + [Blockly.Msg.MIXLY_GETHUMIDITY, "get_SHT_relative_humidity()"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "get_SHT_temperature()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_temperature_TOOLTIP, + "get_SHT_relative_humidity()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_HUM_TOOLTIP, + }; + return TOOLTIPS[mode] + }); + } +}; + +export const sensor_ds18x20 = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput("PIN", Number) + .appendField("DS18x20 " + Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_SENSOR_DS18X20_TOOLTIP); + } +}; + +export const sensor_mpu9250_get_magnetic = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_mpu9250_get_gyro = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_ESP32_SENOR_GYRO) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_ESP32_SENOR_GYRO; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_lm35 = { + init: function () { + this.setColour(SENSOR_HUE); + this.appendDummyInput("") + .appendField("LM35" + Blockly.Msg.MIXLY_TEMP); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_LM35); + } +}; + +export const sensor_button_is_pressed = sensor_mixgo_button_is_pressed; +export const sensor_button_was_pressed = sensor_mixgo_button_was_pressed; +export const sensor_button_get_presses = sensor_mixgo_button_get_presses; +export const sensor_pin_pressed = sensor_mixgo_pin_pressed; +export const sensor_pin_near = sensor_mixgo_pin_near; +export const sensor_mixgo_light = sensor_LTR308; +export const sensor_light = sensor_mixgo_light; +export const sensor_get_acceleration = sensor_mpu9250_get_acceleration; +export const dht11 = sensor_dht11; +export const sensor_field_strength = sensor_mpu9250_field_strength; +export const sensor_temperature = sensor_mpu9250_temperature \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/sensor_extern.js b/mixly/boards/default_src/micropython/blocks/sensor_extern.js new file mode 100644 index 00000000..5249f12a --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/sensor_extern.js @@ -0,0 +1,2455 @@ +import * as Blockly from 'blockly/core'; +import { Profile } from 'mixly'; + +const SENSOR_EXTERN_HUE = '#A58C5B'; //'#9e77c9'//40; + + +export const sensor_mixgo_extern_button_is_pressed = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_PRESSED); + this.appendValueInput("STAT") + .appendField(Blockly.Msg.MIXLY_ELECLEVEL); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_IS_PRESSED); + } +}; + +export const sensor_mixgo_extern_button_was_pressed = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WAS_PRESSED); + this.appendValueInput("STAT") + .appendField(Blockly.Msg.MIXLY_ELECLEVEL); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_WAS_PRESSED); + } +}; + +export const sensor_mixgo_extern_button_get_presses = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_PRESSES); + this.appendValueInput('VAR') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_GET_PRESSES_TIME); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_BUTTON + Blockly.Msg.MIXLY_GET_PRESSES); + } +}; + +export const sensor_mixgo_extern_button_attachInterrupt = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RISING, "machine.Pin.IRQ_RISING"], + [Blockly.Msg.MIXLY_FALLING, "machine.Pin.IRQ_FALLING"], + [Blockly.Msg.MIXLY_CHANGE, "(machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING)"] + ]), "mode"); + this.appendValueInput('DO') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_ATTACHINTERRUPT); + } +}; + +export const sensor_mpu9250_attachGestureInterrupt = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_shake, "shake"], + [Blockly.Msg.MIXLY_UP, "up"], + [Blockly.Msg.MIXLY_DOWN, "down"], + [Blockly.Msg.MIXLY_LEFT, "left"], + [Blockly.Msg.MIXLY_RIGHT, "right"], + [Blockly.Msg.MIXLY_MICROBIT_face_up, "face up"], + [Blockly.Msg.MIXLY_MICROBIT_face_down, "face down"], + [Blockly.Msg.MIXLY_MICROBIT_freefall, "freefall"], + ["3g", "3g"], ["6g", "6g"], ["8g", "8g"] + ]), "gesture"); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('gesture'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT; + var mode1 = Blockly.Msg.MSG.catSensor; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_STATE; + var mode3 = Blockly.Msg.MIXLY_MICROBIT_PERFORMANCE + var TOOLTIPS = { + 'shake': Blockly.Msg.MIXLY_MICROBIT_shake, + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT, + 'face up': Blockly.Msg.MIXLY_MICROBIT_face_up, + 'face down': Blockly.Msg.MIXLY_MICROBIT_face_down, + 'freefall': Blockly.Msg.MIXLY_MICROBIT_freefall, + '3g': '3g', + '6g': '6g', + '8g': '8g' + }; + return mode0 + mode1 + mode2 + TOOLTIPS[mode] + mode3; + }); + } +}; + +export const sensor_adxl345_get_acceleration = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_ADXL345) + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION1; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_light_level = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_LIGHT_LEVEL) + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SENSOR_LIGHT_LEVEL_TOOLTIP); + } +}; + +export const sensor_dht11 = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField(new Blockly.FieldDropdown([ + ['DHT11', 'DHT11'], + ['DHT22', 'DHT22']//, ['DHT21', '21'], ['DHT33', '33'], ['DHT44', '44'] + ]), 'TYPE') + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(sensor_dht11.METHOD), "WHAT"); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('WHAT'); + var TOOLTIPS = { + 'temperature': Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_GET_TEM, + 'relative_humidity': Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_GET_HUM, + 'tempandhum': Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_GET_TEM_HUM + }; + return TOOLTIPS[op]; + }); + }, + METHOD: [ + [Blockly.Msg.MIXLY_GETTEMPERATUE, 'temperature'], + [Blockly.Msg.MIXLY_GETHUMIDITY, 'humidity'] + ] +}; + +export const sensor_mixgo_extern_light = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_VALUE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ESP32_SENSOR_NIXGO_LIGHT_TOOLTIP); + } +}; + +export const sensor_mixgo_extern_sound = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_SOUND); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_VALUE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ESP32_SENSOR_NIXGO_SOUND_TOOLTIP); + } +}; + +export const sensor_mixgo_extern_pin_near = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "left"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "right"] + ]), "direction") + .appendField(Blockly.Msg.MIXLY_ESP32_NEAR); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('direction'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + var TOOLTIPS = { + 'left': Blockly.Msg.TEXT_TRIM_LEFT, + 'right': Blockly.Msg.TEXT_TRIM_RIGHT, + }; + return mode0 + TOOLTIPS[mode] + mode1 + }); + } +}; + +export const sensor_bmp = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_ALTITUDE_SENSOR + " BMP280") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETTEMPERATUE, "get_BMP_temperature()"], + [Blockly.Msg.MIXLY_GETPRESSURE, "get_BMP_pressure()"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "get_BMP_temperature()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_BMP_temperature_TOOLTIP, + "get_BMP_pressure()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_BMP_press_TOOLTIP, + }; + return TOOLTIPS[mode] + }); + } +}; + +export const sensor_sht = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TEMP_AND_HUMIDITY_SENSOR + " SHT20") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETTEMPERATUE, "get_SHT_temperature()"], + [Blockly.Msg.MIXLY_GETHUMIDITY, "get_SHT_relative_humidity()"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "get_SHT_temperature()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_temperature_TOOLTIP, + "get_SHT_relative_humidity()": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_HUM_TOOLTIP, + }; + return TOOLTIPS[mode] + }); + } +}; + +export const sensor_DS18X20 = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN", Number) + .appendField("DS18X20 " + Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_SENSOR_DS18X20_TOOLTIP); + } +}; + +export const sensor_lm35 = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField("LM35" + Blockly.Msg.MIXLY_TEMP); + this.appendValueInput("PIN", Number) + .appendField(Blockly.Msg.MIXLY_PIN) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_LM35); + } +}; + +//pe +export const sensor_use_i2c_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('I2CSUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "I2C") + .setCheck("var"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT + "(LTR308ALS)", "LTR308"], + [Blockly.Msg.MIXLY_COLOR_SENSOR + "(LTR381RGB)", "LTR381RGB"], + [Blockly.Msg.MIXLY_COLOR_SENSOR + "(UCS12071)", "UCS12071"], + [Blockly.Msg.MIXLY_EXTERN_LIGHTUV + "(LTR390UV)", "LTR390UV"], + [Blockly.Msg.MIXLY_ALTITUDE_SENSOR + "(HP203X)", "HP203X"], + [Blockly.Msg.MIXLY_ALTITUDE_SENSOR + "(SPL06_001)", "SPL06_001"], + [Blockly.Msg.MIXLY_ALTITUDE_SENSOR + "(MS5611)", "MS5611"], + [Blockly.Msg.MIXLY_ALTITUDE_SENSOR + "(BMP280)", "BMP280"], + [Blockly.Msg.MIXLY_TEMP_AND_HUMIDITY_SENSOR + "(SHTC3)", "SHTC3"], + [Blockly.Msg.MIXLY_TEMP_AND_HUMIDITY_SENSOR + "(AHT21)", "AHT21"], + [Blockly.Msg.MIXLY_TEMP_AND_HUMIDITY_SENSOR + "(SHT20)", "SHT20"], + [Blockly.Msg.MIXLY_LASER_RANGE_SENSOR + "(VL53L0X)", "VL53L0X"], + [Blockly.Msg.MIXLY_GEOMAGNETIC_SENSOR + "(QMC5883L)", "QMC5883L"], + [Blockly.Msg.MIXLY_ESP32_MAX30102 + "(MAX30102)", "MAX30102"], + [Blockly.Msg.HTML_COLOUR + "、" + Blockly.Msg.MIXLY_ENVIRONMENT_LIGHT + "、" + Blockly.Msg.MIXLY_NEXT + "、" + Blockly.Msg.MIXLY_ESP32_APDS9960 + "(APDS9960)", "APDS9960"], + [Blockly.Msg.MIXLY_NINE_AXIS_SENSOR + "(MPU9250)", "MPU9250"], + [Blockly.Msg.MixGo_MPU9250 + "(ADXL345)", "ADXL345"], + ["RFID", "RFID"], + [Blockly.Msg.MIXLY_RADAR_SENSOR + "(CBR817)", "CBR817"], + [Blockly.Msg.MIXLY_AipSpeech_asr + "(CI130X)", "CI130X"], + [Blockly.Msg.MIXLY_TVOC_CO2_SENSOR + "(AGS10)","AGS10" ] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + + } +}; + +export const radar_set_DETECTION_THRESHOLD = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_RADAR + 'CBR817') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXlY_INTERACTION) + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_DETECTION_THRESHOLD); + this.appendValueInput('VAR2') + .appendField(Blockly.Msg.MIXLY_DELAY_TIME); + this.appendDummyInput() + .appendField('ms'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_THRESHOLD_TOOLTIP + ' ; ' + Blockly.Msg.MIXLY_DELAY_TIME_RANGE) + } +}; + +export const radar_set_DETECTION_THRESHOLD_SANT = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RADAR) + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXlY_INTERACTION) + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_DETECTION_THRESHOLD); + this.appendValueInput('VAR2') + .appendField(Blockly.Msg.MIXLY_DELAY_TIME); + this.appendDummyInput() + .appendField('ms'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_THRESHOLD_TOOLTIP + ' ; ' + Blockly.Msg.MIXLY_DELAY_TIME_RANGE) + } +}; + +export const interaction_whether_to_interaction = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_RADAR + 'CBR817') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET_TO_INTERACTION) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const interaction_whether_to_interaction_SANT = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RADAR) + .appendField(Blockly.Msg.MIXLY_GET_TO_INTERACTION) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const CI130X_IDENTIFY_AND_SAVE = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + 'CI130X') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_IDENTIFY_ONCE_AND_SAVE) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const CI130X_GET_WHETHER_IDENTIFY = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + 'CI130X') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_HELLO_XIAOZHI, "1"], + [Blockly.Msg.MIXLY_XIAOZHIXIAOZHI, "2"], + [Blockly.Msg.MIXLY_THE_FIRST, "3"], + [Blockly.Msg.MIXLY_THE_SECOND, "4"], + [Blockly.Msg.MIXLY_THE_THIRD, "5"], + [Blockly.Msg.MIXLY_THE_FOURTH, "6"], + [Blockly.Msg.MIXLY_THE_FIFTH, "7"], + [Blockly.Msg.MIXLY_THE_SIXTH, "8"], + [Blockly.Msg.MIXLY_THE_SEVENTH, "9"], + [Blockly.Msg.MIXLY_THE_EIGHTH, "10"], + [Blockly.Msg.MIXLY_THE_NINTH, "11"], + [Blockly.Msg.MIXLY_THE_TENTH, "12"], + [Blockly.Msg.MIXLY_THE_ELEVENTH, "13"], + [Blockly.Msg.MIXLY_THE_TWELFTH, "14"], + [Blockly.Msg.MIXLY_THE_13TH, "15"], + [Blockly.Msg.MIXLY_THE_14TH, "16"], + [Blockly.Msg.MIXLY_THE_15TH, "17"], + [Blockly.Msg.MIXLY_THE_16TH, "18"], + [Blockly.Msg.MIXLY_THE_17TH, "19"], + [Blockly.Msg.MIXLY_THE_18TH, "20"], + [Blockly.Msg.MIXLY_THE_19TH, "21"], + [Blockly.Msg.MIXLY_THE_20TH, "22"], + [Blockly.Msg.MIXLY_Turn_on_the_lights, "23"], + [Blockly.Msg.MIXLY_Turn_off_the_lights, "24"], + [Blockly.Msg.MIXLY_Turn_up_the_brightness, "25"], + [Blockly.Msg.MIXLY_Turn_down_the_brightness, "26"], + [Blockly.Msg.MIXLY_Set_it_to_red, "27"], + [Blockly.Msg.MIXLY_Set_it_to_orange, "28"], + [Blockly.Msg.MIXLY_Set_it_to_yellow, "29"], + [Blockly.Msg.MIXLY_Set_it_to_green, "30"], + [Blockly.Msg.MIXLY_Set_it_to_cyan, "31"], + [Blockly.Msg.MIXLY_Set_it_to_blue, "32"], + [Blockly.Msg.MIXLY_Set_it_to_purple, "33"], + [Blockly.Msg.MIXLY_Set_it_to_white, "34"], + [Blockly.Msg.MIXLY_Turn_on_the_fan, "35"], + [Blockly.Msg.MIXLY_Turn_off_the_fan, "36"], + [Blockly.Msg.MIXLY_First_gear, "37"], + [Blockly.Msg.MIXLY_Wind_speed_second, "38"], + [Blockly.Msg.MIXLY_Third_gear, "39"], + [Blockly.Msg.MIXLY_Previous, "40"], + [Blockly.Msg.MIXLY_Next_page, "41"], + [Blockly.Msg.MIXLY_Show_smiley_face, "42"], + [Blockly.Msg.MIXLY_Show_crying_face, "43"], + [Blockly.Msg.MIXLY_Show_love, "44"], + [Blockly.Msg.MIXLY_Close_display, "45"], + [Blockly.Msg.MIXLY_Start_execution, "46"], + [Blockly.Msg.MIXLY_FORWARD, "47"], + [Blockly.Msg.MIXLY_BACKWARD, "48"], + [Blockly.Msg.MIXLY_TURNLEFT, "49"], + [Blockly.Msg.MIXLY_TURNRIGHT, "50"], + [Blockly.Msg.MIXLY_STOP, "51"], + [Blockly.Msg.MIXLY_Accelerate, "52"], + [Blockly.Msg.MIXLY_retard, "53"], + [Blockly.Msg.ROTATION_FORWARD, "54"], + [Blockly.Msg.ROTATION_BACKWARD, "55"], + [Blockly.Msg.MIXLY_Query_temperature, "56"], + [Blockly.Msg.MIXLY_Query_humidity, "57"], + [Blockly.Msg.MIXLY_Query_brightness, "58"], + [Blockly.Msg.MIXLY_Query_sound, "59"], + [Blockly.Msg.MIXLY_Query_time, "60"], + [Blockly.Msg.MIXLY_Query_distance, "61"], + [Blockly.Msg.MIXLY_Query_pressure, "62"], + [Blockly.Msg.MIXLY_Query_key, "63"], + [Blockly.Msg.MIXLY_Query_touch, "64"], + [Blockly.Msg.MIXLY_Query_color, "65"] + ]), "cmd") + .appendField(Blockly.Msg.MIXLY_WHETHER + Blockly.Msg.MIXLY_BE_IDENTIFIED); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const CI130X_GET_THE_RECOGNIZED_CMD = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + 'CI130X') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RECOGNIZED_STATE, "status1"], + [Blockly.Msg.MIXLY_WHETHER_BROADCAST, "status2"], + [Blockly.Msg.MIXLY_THE_RECOGNIZED_CMD, "result"] + ]), "key") + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_CI130X_GET_THE_RECOGNIZED_STATE_TOOLTIP); + } +}; + +export const CI130X_BROADCAST = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + 'CI130X') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MP3_PLAY) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_INOUT_PULL_NONE, "None"], + [Blockly.Msg.MIXLY_WIND_SPEED, "154"], + [Blockly.Msg.MIXLY_HYETAL, "155"], + [Blockly.Msg.MIXLY_TEMPERATURE, "156"], + [Blockly.Msg.MIXLY_Humidity, "157"], + [Blockly.Msg.MIXLY_Altitude, "158"], + [Blockly.Msg.MIXLY_SOUND, "159"], + [Blockly.Msg.MIXLY_BRIGHTNESS, "160"], + [Blockly.Msg.ME_GO_HALL_SENSOR_DISTANCE, "161"], + [Blockly.Msg.MIXLY_SERVO, "162"], + [Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, "163"], + [Blockly.Msg.MIXLY_BUTTON2, "164"], + [Blockly.Msg.MIXLY_ESP32_TOUCH, "165"], + [Blockly.Msg.MIXLY_PAY, "166"], + [Blockly.Msg.MIXLY_CARSH_CHANGE, "167"], + [Blockly.Msg.MIXLY_COUNTDOWN, "168"], + [Blockly.Msg.MIXLY_TIMING, "169"], + [Blockly.Msg.MIXLY_AT_THE_MOMENT, "170"], + [Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE, "171"], + [Blockly.Msg.MIXLY_FORWARD, "172"], + [Blockly.Msg.MIXLY_BACKWARD, "173"], + [Blockly.Msg.MIXLY_TURNLEFT, "174"], + [Blockly.Msg.MIXLY_TURNRIGHT, "175"], + [Blockly.Msg.MIXLY_STOP, "176"], + [Blockly.Msg.MIXLY_Accelerate, "177"], + [Blockly.Msg.MIXLY_retard, "178"], + [Blockly.Msg.ROTATION_FORWARD, "179"], + [Blockly.Msg.ROTATION_BACKWARD, "180"], + [Blockly.Msg.TUPLE_JOIN, "181"], + [Blockly.Msg.MIXLY_SHOW, "182"], + [Blockly.Msg.MIXLY_LAMPLIGHT, "183"], + [Blockly.Msg.MIXLY_ACCELERATION, "184"] + ]), "star"); + this.appendValueInput('NUM') + .appendField(Blockly.Msg.MIXLY_NUMBER); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_UNIT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_INOUT_PULL_NONE, "None"], + [Blockly.Msg.MIXLY_YEAR, "117"], + [Blockly.Msg.MIXLY_MONTH, "118"], + [Blockly.Msg.MIXLY_DAY, "119"], + [Blockly.Msg.MIXLY_HOUR, "120"], + [Blockly.Msg.MIXLY_MINUTE, "121"], + [Blockly.Msg.MIXLY_SECOND, "122"], + [Blockly.Msg.MIXLY_WEEK2, "123"], + [Blockly.Msg.MIXLY_RMB_UNIT, "124"], + [Blockly.Msg.blockpy_setheading_degree, "125"], + [Blockly.Msg.MIXLY_GEAR, "126"], + [Blockly.Msg.MIXLY_LAYER, "127"], + [Blockly.Msg.MIXLY_GRAM, "128"], + [Blockly.Msg.MIXLY_METER, "129"], + [Blockly.Msg.MIXLY_CENTIMETER, "130"], + [Blockly.Msg.MIXLY_MILLIMETER, "131"], + [Blockly.Msg.MIXLY_LUMEN, "132"], + [Blockly.Msg.MIXLY_DECIBEL, "133"], + [Blockly.Msg.MIXLY_hectopascal, "134"], + [Blockly.Msg.MIXLY_PERCENT, "135"], + [Blockly.Msg.MIXLY_CELSIUS, "136"], + [Blockly.Msg.MIXLY_METER_PER_SEC, "137"], + [Blockly.Msg.MIXLY_MICROBIT_Turn_on_display, "138"], + [Blockly.Msg.MIXLY_MICROBIT_Turn_off_display, "139"], + [Blockly.Msg.MIXLY_SUCCESS, "140"], + [Blockly.Msg.MIXLY_FAILED, "141"], + [Blockly.Msg.MIXLY_WRONG, "142"], + [Blockly.Msg.MIXLY_GOOD, "143"], + [Blockly.Msg.MIXLY_blockpy_set_add, "144"], + [Blockly.Msg.MIXLY_DECREASE, "145"], + [Blockly.Msg.COLOUR_RGB_RED, "146"], + [Blockly.Msg.COLOUR_RGB_ORANGE, "147"], + [Blockly.Msg.COLOUR_YELLOW, "148"], + [Blockly.Msg.COLOUR_RGB_GREEN, "149"], + [Blockly.Msg.COLOUR_CYAN, "150"], + [Blockly.Msg.COLOUR_RGB_BLUE, "151"], + [Blockly.Msg.COLOUR_RGB_PURPLE, "152"], + [Blockly.Msg.COLOUR_RGB_WHITE, "153"] + ]), "end"); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const CI130X_SET_SYSTEM_CMD = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_AipSpeech_asr + 'CI130X') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_SYSTEM + Blockly.Msg.MIXLY_CMD) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MILXY_ENTER_WAKE_UP, "1"], + [Blockly.Msg.MIXLY_INCREASE_VOLUME, "202"], + [Blockly.Msg.MIXLY_REDUCE_VOLUME, "203"], + [Blockly.Msg.MIXLY_MAX_VOLUME, "204"], + [Blockly.Msg.MIXLY_MINIMUM, "205"], + [Blockly.Msg.MIXLY_OPEN_RESPONSE, "206"], + [Blockly.Msg.MIXLY_CLOSE_RESPONSE, "207"], + [Blockly.Msg.MIXLY_QUIT_WAKE_UP, "208"] + ]), "cmd") + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +}; + +export const sensor_MAX30102_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MAX30102 + " MAX30102"); + this.appendValueInput('SUB') + //.appendField("BMP280") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_MAX30102_IR, "[0]"], + [Blockly.Msg.MIXLY_ESP32_MAX30102_RED, "[1]"], + [Blockly.Msg.MIXLY_ESP32_MAX30102_IR + ',' + Blockly.Msg.MIXLY_ESP32_MAX30102_RED, ""], + ]), "key") + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_APDS9960_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_APDS9960 + " APDS9960"); + this.appendValueInput('SUB') + //.appendField("BMP280") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ESP32_APDS9960_COLOR, "color"], + [Blockly.Msg.MIXLY_ESP32_APDS9960_GESTURE, "gesture"], + [Blockly.Msg.MIXLY_ESP32_APDS9960_APPROACH, "proximity"], + ]), "key") + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_LTR308_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT + " LTR308ALS"); + this.appendValueInput('SUB') + //.appendField("BMP280") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_LIGHT_INTENSITY); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_ltr381_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.HTML_COLOUR + Blockly.Msg.MSG.catSensor + " LTR381RGB") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GET + Blockly.Msg.HTML_COLOUR, "[2]"], + [Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_IR_STRENGTH, "[1]"], + [Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_LIGHT_STRENGTH, "[0]"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_ucs12071_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.HTML_COLOUR + Blockly.Msg.MSG.catSensor + " UCS12071") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GET + 'RGB' + Blockly.Msg.HTML_COLOUR, "0"], + [Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_RGB_RAW, "1"], + [Blockly.Msg.MIXLY_GET_ENV_LIGHT + Blockly.Msg.MIXLY_BRIGHTNESS, "2"], + [Blockly.Msg.GET_IR_STRENGTH + Blockly.Msg.MIXLY_BRIGHTNESS, "3"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_LTR390UV_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_EXTERN_LIGHTUV + " LTR390UV") + .setCheck("var"); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GET_ENV_LIGHT, "E"], + [Blockly.Msg.MIXLY_GET_ULTRAVIOLET, "U"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_VL530LX_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LASER_RANGE + " VL53L0X"); + this.appendValueInput('SUB') + //.appendField("BMP280") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_DISTANCE + '(mm)'); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_shtc3_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TEM_HUM + " SHTC3") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETTEMPERATUE, "temperature"], + [Blockly.Msg.MIXLY_GETHUMIDITY, "humidity"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "temperature": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_temperature_TOOLTIP, + "humidity": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_HUM_TOOLTIP + }; + return TOOLTIPS[mode] + }); + } +}; + +export const sensor_aht11_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TEM_HUM + " AHT21") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETTEMPERATUE, "temperature"], + [Blockly.Msg.MIXLY_GETHUMIDITY, "humidity"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "temperature": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_temperature_TOOLTIP, + "relative_humidity": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_HUM_TOOLTIP + }; + return TOOLTIPS[mode] + }); + } +}; + +export const sensor_hp203_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_Altitude + Blockly.Msg.MSG.catSensor + " HP203X") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETPRESSURE, "pressure()"], + [Blockly.Msg.MIXLY_GETTEMPERATUE, "temperature()"], + [Blockly.Msg.MIXLY_GET_ALTITUDE, "altitude()"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_spl06_001_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_Altitude + Blockly.Msg.MSG.catSensor + " SPL06_001") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETPRESSURE, "pressure()"], + [Blockly.Msg.MIXLY_GETTEMPERATUE, "temperature()"], + [Blockly.Msg.MIXLY_GET_ALTITUDE, "altitude()"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_ms5611_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_Altitude + Blockly.Msg.MSG.catSensor + " MS5611") + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETPRESSURE, "pressure()"], + [Blockly.Msg.MIXLY_GETTEMPERATUE, "temperature()"], + [Blockly.Msg.MIXLY_GET_ALTITUDE, "altitude()"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_ms5611_extern_altitude = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_Altitude + Blockly.Msg.MSG.catSensor + " MS5611") + .setCheck("var"); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_REF_TO_PRESSURE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CAL_TO_ALTITUDE); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_QMC5883L_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MIXGOPE_FIELD + Blockly.Msg.MSG.catSensor + " QMC5883L") + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, "get_bearing()"], + [Blockly.Msg.MIXLY_TEMPERATURE, "get_temp()"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_mpu9250_gesture = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_shake, "shake"], + [Blockly.Msg.MIXLY_UP, "up"], + [Blockly.Msg.MIXLY_DOWN, "down"], + [Blockly.Msg.MIXLY_LEFT, "left"], + [Blockly.Msg.MIXLY_RIGHT, "right"], + [Blockly.Msg.MIXLY_MICROBIT_face_up, "face up"], + [Blockly.Msg.MIXLY_MICROBIT_face_down, "face down"] + ]), "gesture"); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('gesture'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT; + var mode1 = Blockly.Msg.MSG.catSensor; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_STATE; + var mode3 = Blockly.Msg.MIXLY_MICROBIT_PERFORMANCE + var TOOLTIPS = { + 'shake': Blockly.Msg.MIXLY_MICROBIT_shake, + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT, + 'face up': Blockly.Msg.MIXLY_MICROBIT_face_up, + 'face down': Blockly.Msg.MIXLY_MICROBIT_face_down, + // 'freefall':Blockly.Msg.MIXLY_MICROBIT_freefall, + // '3g': '3g', + // '6g': '6g', + // '8g': '8g' + }; + return mode0 + mode1 + mode2 + TOOLTIPS[mode] + mode3; + }); + } +}; + +export const sensor_mpu9250_get_acceleration = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_NINE_AXIS_SENSOR + " MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION1; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_mpu9250_get_magnetic = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_NINE_AXIS_SENSOR + " MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_mpu9250_get_gyro = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_NINE_AXIS_SENSOR + " MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_ESP32_SENOR_GYRO) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_ESP32_SENOR_GYRO; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_mpu9250_calibrate_compass = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_NINE_AXIS_SENSOR + " MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS); + } +}; + +export const sensor_mpu9250_temperature = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_NINE_AXIS_SENSOR + " MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE) + this.setOutput(true, Number); + this.setInputsInline(true); + + this.setTooltip(Blockly.Msg.MIXLY_GETTEMPERATUE); + } +}; + +export const sensor_mpu9250_field_strength = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET_COMPASS) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH, 'strength'], + [Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, 'heading'] + ]), 'compass'); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('compass'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_GET_COMPASS; + var TOOLTIPS = { + 'strength': Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH, + 'heading': Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + }; + return mode0 + TOOLTIPS[mode]; + }); + } +}; + +export const sensor_compass_reset = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("MPU9250") + .setCheck("var"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_COMPASS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Reset_COMPASS); + } +}; + +export const sensor_use_spi_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SPISUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "SPI") + .setCheck("var"); + this.appendValueInput('PINSUB') + .appendField("CS") + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + ["RFID", "RFID"], + ["WS-LoRa", "Weather"] + ]), "key"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setFieldValue("RFID", "key"); + } +}; + +export const extern_rfid_read = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField("RFID" + Blockly.Msg.MIXLY_RFID_READ_CARD); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendValueInput('SECTOR') + .appendField(Blockly.Msg.MIXLY_LIST_INDEX) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RFID_READ_CARD_UID, "id"], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ALL, "content"], + [Blockly.Msg.MIXLY_ALL, "ALL"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const extern_rfid_readid = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField("RFID" + Blockly.Msg.MIXLY_RFID_READ_CARD); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RFID_READ_CARD_UID); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const extern_rfid_readcontent = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField("RFID" + Blockly.Msg.MIXLY_RFID_READ_CARD); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendValueInput('SECTOR') + .appendField(Blockly.Msg.MIXLY_LIST_INDEX) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ALL); + this.setOutput(true, 'Tuple'); + this.setInputsInline(true); + } +}; + +export const extern_rfid_write = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_RFID_WRITE); + this.appendValueInput('SUB') + .setCheck("var") + this.appendValueInput('SECTOR') + .appendField(Blockly.Msg.MIXLY_LIST_INDEX) + this.appendValueInput('CONTENT') + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_WRITE_NUM) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const extern_rfid_write_return = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_RFID_WRITE); + this.appendValueInput('SUB') + .setCheck("var") + this.appendValueInput('SECTOR') + .appendField(Blockly.Msg.MIXLY_LIST_INDEX) + this.appendValueInput('CONTENT') + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_WRITE_NUM) + this.appendDummyInput() + .appendField(Blockly.Msg.RETURN_SUCCESS_OR_NOT); + this.setInputsInline(true); + this.setOutput(true, Boolean); + } +}; + +export const extern_rfid_status = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField("RFID"); + this.appendValueInput('SUB') + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RFID_SCAN_OK, "0"], + [Blockly.Msg.MIXLY_RFID_SCAN_NOTAGERR, "1"], + [Blockly.Msg.MIXLY_RFID_SCAN_ERROR, "2"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +//--------------------待写气象数据 +export const weather_data = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("无线气象站" + " WS-LoRa") + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown([ + ["全部(元组)", "data()[0]"], + ["全部(json)", "data()[1]"], + ["全部(json,附带位置信息)", "data()[2]"], + ["编号", "data()[0][0]"], + ["电量", "data()[0][1]"], + ["风速", "data()[0][2]"], + ["阵风", "data()[0][3]"], + ["风向", "data()[0][4]"], + ["雨量", "data()[0][5]"], + ["温度", "data()[0][6]"], + ["湿度", "data()[0][7]"], + ["光照", "data()[0][8]"], + ["紫外线", "data()[0][9]"], + ["大气压", "data()[0][10]"], + ["信号强度", "data()[0][11]"], + ["信噪比", "data()[0][12]"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip("返回气象数据元组 data= (设备id,电池状态,风速m/s,阵风m/s,风向°,雨量mm,温度℃,湿度%,光照Lux,UVI,大气压Pa,信号强度dB,信噪比dB)"); + } +}; + +export const weather_have_data = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("无线气象站" + " WS-LoRa") + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SERIAL_AVAILABLE) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const weather_uart_mixio = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("无线气象站" + " WS-LoRa") + .setCheck("var"); + this.appendValueInput('BASE') + .appendField("以主题") + this.appendDummyInput("") + .appendField("串口发送至MixIO") + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const weather_set_label = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField("无线气象站" + " WS-LoRa") + .setCheck("var"); + this.itemCount_ = 2; + this.updateShape_(); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setInputsInline(true); + this.setMutator(new Blockly.icons.MutatorIcon(['weather_set_label_item'], this)); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(); + }, + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('weather_set_label_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('weather_set_label_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i) + .connection.connect(connections[i]); + } + } + }, + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_GPS_LOCATION + Blockly.Msg.mixpy_PYLAB_TICKS_TAG + '(id,long,lat)'); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_GPS_LOCATION + Blockly.Msg.mixpy_PYLAB_TICKS_TAG + '(id,long,lat)'); + } + } + } + } +}; + +export const weather_set_label_container = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETTING + Blockly.Msg.MIXLY_GPS_LOCATION + Blockly.Msg.mixpy_PYLAB_TICKS_TAG); + this.appendStatementInput('STACK'); + this.contextMenu = false; + } +}; + +export const weather_set_label_item = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.contextMenu = false; + } +}; + +export const sensor_mixgoce_hot_wheel_is_touched = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_HOT_WHEEL) + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_UP, "4"], + [Blockly.Msg.MIXLY_DOWN, "2"], + [Blockly.Msg.MIXLY_LEFT, "3"], + [Blockly.Msg.MIXLY_RIGHT, "1"], + ["OK", "0"] + ]), "key"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_DATA, "value"], + [Blockly.Msg.MIXLY_PULSEIN_STAT, "is_touched()"] + ]), "stat"); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(); + } +}; + +export const sensor_mixgoce_hot_wheel_degrees = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_HOT_WHEEL) + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + '(-180°~180°)'); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(); + } +}; + +export const esp32_s2_weather_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.ForecastType + Blockly.Msg.MSG.catSensor); + this.appendValueInput('wd') + .setCheck(Number) + .appendField('wd'); + this.appendValueInput('ws') + .setCheck(Number) + .appendField('ws'); + this.appendValueInput('rain') + .setCheck(Number) + .appendField('rain'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const esp32_s2_weather_wd = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ForecastType + Blockly.Msg.MSG.catSensor) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.ForecastFx) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const esp32_s2_weather_rain = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('rain') + .appendField(Blockly.Msg.ForecastType + Blockly.Msg.MSG.catSensor) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RAIN_TIME + Blockly.Msg.MIXLY_RAIN) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const esp32_s2_weather_ws = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ForecastType + Blockly.Msg.MSG.catSensor) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.blynk_IOT_IR_FAN, "0"], + [Blockly.Msg.MIXLY_WIND_RATING, "1"], + [Blockly.Msg.blynk_IOT_IR_FAN + Blockly.Msg.MIXLY_WIND_RATING, "ALL"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const HCSR04 = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_CHAOSHENGBO); + this.appendValueInput("PIN1", Number) + .appendField('Trig #') + .setCheck(Number); + this.appendValueInput("PIN2", Number) + .appendField('Echo #') + .setCheck(Number); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_CHAOSHENGBO); + } + +}; + +//PS2 +export const PS2_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.PS2); + this.appendDummyInput("") + .appendField('CLK#') + .appendField(new Blockly.FieldDropdown(Profile.default.output_pin), "PS2_CLK") + .appendField('DOU#') + .appendField(new Blockly.FieldDropdown(Profile.default.output_pin), "PS2_DOU") + .appendField('DIN#') + .appendField(new Blockly.FieldDropdown(Profile.default.output_pin), "PS2_DIN") + .appendField('CS#') + .appendField(new Blockly.FieldDropdown(Profile.default.output_pin), "PS2_CS"); + // this.appendDummyInput("") + // .appendField(Blockly.Msg.PS2_setRumble) + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_ON,"true"],[Blockly.Msg.MIXLY_OFF,"false"]]), "rumble"); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + } +}; + +const PSBUTTON = [ + [Blockly.Msg.PS2_TRIANGLE, "PSB_GREEN"], + [Blockly.Msg.PS2_CIRCLE, "PSB_RED"], + [Blockly.Msg.PS2_CROSS, "PSB_BLUE"], + [Blockly.Msg.PS2_SQUARE, "PSB_PINK"], + [Blockly.Msg.PS2_L1, "PSB_L1"], + [Blockly.Msg.PS2_L2, "PSB_L2"], + // ["PSB_L3","PSB_L3"], + [Blockly.Msg.PS2_R1, "PSB_R1"], + [Blockly.Msg.PS2_R2, "PSB_R2"], + // ["PSB_R3","PSB_R3"], + [Blockly.Msg.PS2_UP, "PSB_PAD_UP"], + [Blockly.Msg.PS2_RIGHT, "PSB_PAD_RIGHT"], + [Blockly.Msg.PS2_DOWN, "PSB_PAD_DOWN"], + [Blockly.Msg.PS2_LEFT, "PSB_PAD_LEFT"], + [Blockly.Msg.PS2_SELECT, "PSB_SELECT"], + [Blockly.Msg.PS2_START, "PSB_START"] +]; + +// +export const PS2_vibration = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.PS2 + Blockly.Msg.PS2_setRumble) + .appendField(Blockly.Msg.MIXLY_STM32_OLED_SMALL + Blockly.Msg.MSG.catActuator_motor) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_OFF, "0"], + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_ON, "1"], + ]), "smotorstate") + .appendField(Blockly.Msg.MIXLY_STM32_OLED_BIG + Blockly.Msg.MSG.catActuator_motor + Blockly.Msg.MIXLY_MIXGOPE_AMPLITUDE) + this.appendValueInput("AMP", Number) + this.setTooltip(Blockly.Msg.MIXLY_STM32_OLED_BIG + Blockly.Msg.MSG.catActuator_motor + Blockly.Msg.MIXLY_MIXGOPE_AMPLITUDE + "0-100"); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +// +export const PS2_Button = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.PS2_BUTTON) + .appendField(new Blockly.FieldDropdown(PSBUTTON), "psbt") + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_BUTTON_HOLD, "Button"] + // ,[Blockly.Msg.MIXLY_BUTTON_PRESSED, "ButtonPressed"] + // ,[Blockly.Msg.MIXLY_BUTTON_RELEASED,"ButtonReleased"] + // ,[Blockly.Msg.MIXLY_CHANGE,"NewButtonState"] + ]), "btstate"); + this.setOutput(true, Boolean); + this.setTooltip(''); + } +}; + +// +export const PS2_State = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.PS2_BUTTON) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_PULSEIN_STAT, "0"] + , [Blockly.Msg.MIXLY_MICROBIT_JS_I2C_VALUE, "1"] + // ,[Blockly.Msg.MIXLY_BUTTON_RELEASED,"ButtonReleased"] + // ,[Blockly.Msg.MIXLY_CHANGE,"NewButtonState"] + ]), "btstate"); + this.setOutput(true, Boolean); + this.setTooltip(''); + } +}; + +export const PS2_Buttons = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.PS2_BUTTON) + .appendField(new Blockly.FieldDropdown(PSBUTTON), "psbt") + this.setOutput(true, Boolean); + this.setTooltip(''); + } +}; + +export const PS2_stk = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.PS2_stick) + .appendField(new Blockly.FieldDropdown(PS2_stk.PSSTK), "psstk"); + this.setOutput(true, Number); + this.setTooltip(''); + }, + PSSTK: [ + [Blockly.Msg.PS2_RX, "0"], + [Blockly.Msg.PS2_RY, "1"], + [Blockly.Msg.PS2_LX, "2"], + [Blockly.Msg.PS2_LY, "3"], + ] +}; + +export const PS2_init_new = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.PS2); + this.appendValueInput('CLK') + .appendField('CLK#'); + this.appendValueInput('DOU') + .appendField('DOU#'); + this.appendValueInput('DIN') + .appendField('DIN#'); + this.appendValueInput('CS') + .appendField('CS#'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + } +}; + +export const PS2_vibration_new = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.PS2); + this.appendDummyInput("") + .appendField(Blockly.Msg.PS2_setRumble) + .appendField(Blockly.Msg.MIXLY_STM32_OLED_SMALL + Blockly.Msg.MSG.catActuator_motor) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_OFF, "0"], + [Blockly.Msg.MIXLY_MICROBIT_PY_COMMUNICATE_ON, "1"], + ]), "smotorstate") + .appendField(Blockly.Msg.MIXLY_STM32_OLED_BIG + Blockly.Msg.MSG.catActuator_motor + Blockly.Msg.MIXLY_MIXGOPE_AMPLITUDE) + this.appendValueInput("AMP", Number) + this.setTooltip(Blockly.Msg.MIXLY_STM32_OLED_BIG + Blockly.Msg.MSG.catActuator_motor + Blockly.Msg.MIXLY_MIXGOPE_AMPLITUDE + "0-100"); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const PS2_Buttons_new = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.PS2); + this.appendDummyInput("") + .appendField(Blockly.Msg.PS2_BUTTON.slice(3)) + .appendField(new Blockly.FieldDropdown(PSBUTTON), "psbt") + .appendField(Blockly.Msg.MIXLY_WAS_PRESSED) + this.setOutput(true, Boolean); + this.setTooltip(''); + } +}; + +export const PS2_stk_new = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.PS2); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_JOYSTICK) + .appendField(new Blockly.FieldDropdown(PS2_stk_new.PSSTK), "psstk"); + this.setOutput(true, Number); + this.setTooltip(''); + }, + PSSTK: [ + [Blockly.Msg.PS2_RX, "RX"], + [Blockly.Msg.PS2_RY, "RY"], + [Blockly.Msg.PS2_LX, "LX"], + [Blockly.Msg.PS2_LY, "LY"], + ] +}; + +export const sensor_use_uart_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "uart") + .appendField(new Blockly.FieldDropdown([ + ["uart1", "uart1"], + ["uart2", "uart2"] + ]), "key"); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PM25_SENSOR, "PM"], + [Blockly.Msg.MIXLY_GNSS_SENSOR, "GNSS"], + [Blockly.Msg.MIXLY_TVOC_CO2_SENSOR, "TVOC"] + ]), "sensor"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const pm25_get_data = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField('PM2.5' + Blockly.Msg.MSG.catSensor) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + ['PM2.5', "[0]"], + ['PM10', "[1]"], + ['(PM2.5, PM10)', ""], + ]), "pm") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CONCENTRATION) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_PM_CONCENTRATION_TOOLTIP); + } +}; + +export const gnss_have_data = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GNSS_SENSOR) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SERIAL_AVAILABLE) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const gnss_get_data = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GNSS_SENSOR) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GPS_TIME, "time"], + [Blockly.Msg.MIXLY_GPS_LOCATION, "locate"], + [Blockly.Msg.MIXLY_PULSEIN_STAT, "status"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + 'time': Blockly.Msg.MIXLY_GNSS_SENSOR_GET_TIME_TOOLTIP, + 'locate': Blockly.Msg.MIXLY_GNSS_SENSOR_GET_LOCATE_TOOLTIP, + 'status': Blockly.Msg.MIXLY_GNSS_SENSOR_GET_STATUS_TOOLTIP + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const tvoc_get_data = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_TVOC_CO2_SENSOR) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TVOC_CO2_SENSOR_GRT_DATA1,"[0]"], + [Blockly.Msg.MIXLY_TVOC_CO2_SENSOR_GRT_DATA2,"[1]"], + [Blockly.Msg.MIXLY_TVOC_CO2_SENSOR_GRT_DATA3,"[2]"], + [Blockly.Msg.MIXLY_TVOC_CO2_SENSOR_GRT_DATA1+"、"+Blockly.Msg.MIXLY_TVOC_CO2_SENSOR_GRT_DATA2+"、"+Blockly.Msg.MIXLY_TVOC_CO2_SENSOR_GRT_DATA3 , ""] + ]),"key") + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +//mixbot/feiyi extern below: +export const robot_button_extern_get_value = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_BUTTON) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.TURTLE_POS) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.mixpy_PL_TEXT_TOP, '[0]'], + [Blockly.Msg.mixpy_PL_TEXT_BOTTOM, '[1]'], + [Blockly.Msg.TEXT_TRIM_LEFT, '[2]'], + [Blockly.Msg.TEXT_TRIM_RIGHT, '[3]'], + [Blockly.Msg.mixpy_PL_TEXT_CENTER, '[4]'] + ]), "num"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_DATA) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const robot_touch_extern_get_value = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_MICROBIT_JS_INOUT_EVENT_TOUCH + Blockly.Msg.MSG.catSensor) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_EXTERN_TOUCHED + "?") + this.setOutput(true, Boolean); + this.setInputsInline(true); + } +}; + +export const robot_infrared_extern_get_value = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_ESP32_EXTERN_NEAR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_DATA) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const robot_infrared_extern_grey_get_value = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_ESP32_EXTERN_GRAY_NEAR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_DATA) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const robot_potentiometer_extern_get_value = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_KNOB_POTENTIOMETER) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_DATA) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const robot_color_extern_get_value = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.HTML_COLOUR + Blockly.Msg.MSG.catSensor) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.HTML_COLOUR + Blockly.Msg.HTML_NAME, '[0]'], + ["RGB" + Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, '[1]'], + [Blockly.Msg.MIXLY_ENVIRONMENT_BRIGHTNESS, '[2]'], + [Blockly.Msg.MIXLY_REFLECTION_BRIGHTNESS, '[3]'], + [Blockly.Msg.MIXLY_ALL, ''] + ]), "color"); + this.setOutput(true, Boolean); + this.setInputsInline(true); + } +}; + +export const mixbot_sensor_extern_get_addr = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXBOT) + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_BUTTON, 'ext_button'], + [Blockly.Msg.MIXLY_MICROBIT_JS_INOUT_EVENT_TOUCH + Blockly.Msg.MSG.catSensor, 'ext_collision'], + [Blockly.Msg.MIXLY_ESP32_EXTERN_NEAR, 'ext_infrared'], + [Blockly.Msg.MIXLY_KNOB_POTENTIOMETER, 'ext_potentiometer'], + [Blockly.Msg.HTML_COLOUR + Blockly.Msg.MSG.catSensor, 'ext_color'], + [Blockly.Msg.MIXLY_EXTERN_SONAR, 'ext_sonar'] + ]), "name") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_EXTERN_GET_ADDR) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const mixbot_sensor_extern_set_addr = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXBOT) + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_BUTTON, 'ext_button'], + [Blockly.Msg.MIXLY_MICROBIT_JS_INOUT_EVENT_TOUCH + Blockly.Msg.MSG.catSensor, 'ext_collision'], + [Blockly.Msg.MIXLY_ESP32_EXTERN_NEAR, 'ext_infrared'], + [Blockly.Msg.MIXLY_KNOB_POTENTIOMETER, 'ext_potentiometer'], + [Blockly.Msg.HTML_COLOUR + Blockly.Msg.MSG.catSensor, 'ext_color'], + [Blockly.Msg.MIXLY_EXTERN_SONAR, 'ext_sonar'] + ]), "name") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXBOT_EXTERN_SET_ADDR) + this.appendValueInput('old') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE); + this.appendValueInput('new') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_UPDATE); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const robot_sonar_extern_get_value = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_EXTERN_SONAR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_DATA + '(cm)') + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const robot_sonar_extern_led = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ME_GO_MOTOR_EXTERN + Blockly.Msg.MIXLY_EXTERN_SONAR) + .appendField(Blockly.Msg.PIN_NUMBERING) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_LEFT, "0"], + [Blockly.Msg.MIXLY_RIGHT, "1"] + ]), "mode"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_EXTERN_INDICATOR_LIGHT) + this.appendValueInput('light') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LCD_NUMBERING); + this.appendValueInput('bright') + .appendField(Blockly.Msg.MIXLY_PULSEIN_STAT) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const sensor_weather_solo_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.weather_solo); + this.appendValueInput('wd') + .appendField('W-D#'); + this.appendValueInput('ws') + .appendField('W-S#'); + this.appendValueInput('rain') + .appendField('Rain#'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + } +}; + +export const sensor_weather_solo_wd = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.weather_solo); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.ForecastFx) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ABBR, "[0]"], + [Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, "[1]"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_weather_solo_ws = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.weather_solo); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.MIXLY_WIND_SPEED) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SPEED + 'm/s', "[0]"], + [Blockly.Msg.MIXLY_WIND_RATING, "[1]"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_weather_solo_rain = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.weather_solo); + this.appendValueInput('time') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RAIN_TIME) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ACCUMULATED, "[0]"], + [Blockly.Msg.MIXLY_AVERAGE, "[1]"] + ]), "key"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RAIN + '(mm)'); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +//educore sensor_extern +export const educore_body_sensor = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_BODY_SENSOR); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_soilhum_sensor = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_SOILHUM_SENSOR); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_temphum_sensor = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_TEMP_AND_HUMIDITY_SENSOR); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_infrared_sensor = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_Infrared_pyroelectric_sensor); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_button_sensor_extern = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.HTML_BUTTON); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const sensor_read_humiture = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GET) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_of) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TEMPERATURE, "0"], + [Blockly.Msg.MIXLY_Humidity, "1"] + ]), "key"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_ultrasonic_sensor = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_EXTERN_SONAR); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const ultrasonic_sensor_read_distance = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GET) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.ME_GO_HALL_SENSOR_DISTANCE); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_temp_sensor = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_TEMP + Blockly.Msg.MIXLY_DS18B20); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_camera_sensor = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_SMARTCAMERA); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const camera_sensor_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_SMARTCAMERA); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_PROCCED) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_AipFace, "FACE_RECOGNIZE"], + [Blockly.Msg.MIXLY_FACE_CLASSIFIER, "FACE_DETECT"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const camera_sensor_result = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_SMARTCAMERA); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_RECOGNIZED_RESULT); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const sensor_weigh_init = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP + 'HX711/720' + Blockly.Msg.MIXLY_WEIGH_SENSOR); + this.appendValueInput('sck') + .appendField('#SCK'); + this.appendValueInput('dat') + .appendField('#DAT'); + this.appendValueInput('pc') + .appendField(Blockly.Msg.MIXLY_Calibration_ratio); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + } +}; + +export const weigh_sensor_get_weight = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_WEIGH_SENSOR) + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_DATA + '(g)') + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const init_matrix_keyboard = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.MIXLY_Keypad) + .setAlign(Blockly.ALIGN_RIGHT) + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(''), 'VAR') + .setAlign(Blockly.ALIGN_RIGHT) + this.appendValueInput('VALUE1') + .appendField(Blockly.Msg.MIXLY_line_tube_foot + '#') + .setAlign(Blockly.ALIGN_RIGHT) + this.appendValueInput('VALUE2') + .appendField(Blockly.Msg.MIXLY_column_tube_foot + '#') + .setAlign(Blockly.ALIGN_RIGHT) + this.appendValueInput('VALUE3') + .appendField(Blockly.Msg.MIXLY_DEFINE_KEYBOARDS) + .setAlign(Blockly.ALIGN_RIGHT) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(false); + } +} + +export const line_tube_foot ={ + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('PIN1') + .appendField('1#') + this.appendValueInput('PIN2') + .appendField('2#') + this.appendValueInput('PIN3') + .appendField('3#') + this.appendValueInput('PIN4') + .appendField('4#') + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const column_tube_foot = { + init: function () { + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('PIN1') + .appendField('1#') + this.appendValueInput('PIN2') + .appendField('2#') + this.appendValueInput('PIN3') + .appendField('3#') + this.appendValueInput('PIN4') + .appendField('4#') + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const define_keyboards = { + init:function(){ + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(''), 'VAR1') + .appendField(new Blockly.FieldTextInput(''), 'VAR2') + .appendField(new Blockly.FieldTextInput(''), 'VAR3') + .appendField(new Blockly.FieldTextInput(''), 'VAR4') + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(''), 'VAR5') + .appendField(new Blockly.FieldTextInput(''), 'VAR6') + .appendField(new Blockly.FieldTextInput(''), 'VAR7') + .appendField(new Blockly.FieldTextInput(''), 'VAR8') + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(''), 'VAR9') + .appendField(new Blockly.FieldTextInput(''), 'VAR10') + .appendField(new Blockly.FieldTextInput(''), 'VAR11') + .appendField(new Blockly.FieldTextInput(''), 'VAR12') + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(''), 'VAR13') + .appendField(new Blockly.FieldTextInput(''), 'VAR14') + .appendField(new Blockly.FieldTextInput(''), 'VAR15') + .appendField(new Blockly.FieldTextInput(''), 'VAR16') + this.setOutput(true); + this.setInputsInline(false); + } +} + +export const get_keboards_value = { + init:function(){ + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(''), 'VAR') + .appendField(Blockly.Msg.MIXLY_Keypad_GETKEY) + this.setOutput(true); + this.setInputsInline(true); + } +} + +export const init_init_rotary_encoder = { + init:function(){ + this.setColour(SENSOR_EXTERN_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_AS + Blockly.Msg.MIXLY_ROTARY_ENCODER) + this.appendValueInput('PIN1') + .appendField('PINA#') + this.appendValueInput('PIN2') + .appendField('PINB#') + this.appendValueInput('KEY') + .appendField('KEY#') + this.appendValueInput('METHOD') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const rotary_key = { + init:function(){ + this.setColour(SENSOR_EXTERN_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ROTARY_ENCODER) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.CLOCKWISE + Blockly.Msg.MIXLY_REVOLVE,"ROT_CW"], + [Blockly.Msg.ANTI_CLOCKWISE + Blockly.Msg.MIXLY_REVOLVE,"ROT_CCW"], + [Blockly.Msg.MIXLY_BUTTON2 + Blockly.Msg.MIXLY_BUTTON_PRESSED, "SW_PRESS"], + [Blockly.Msg.MIXLY_BUTTON2 + Blockly.Msg.MIXLY_BUTTON_RELEASED,"SW_RELEASE"] + ]),"key") + this.setOutput(true); + this.setInputsInline(true); + } +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/sensor_onboard.js b/mixly/boards/default_src/micropython/blocks/sensor_onboard.js new file mode 100644 index 00000000..03241ca3 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/sensor_onboard.js @@ -0,0 +1,1604 @@ +import * as Blockly from 'blockly/core'; +import { Profile } from 'mixly'; +import { + sensor_dht11, + sensor_mpu9250_field_strength, + sensor_mpu9250_temperature +} from './sensor_extern.js'; + +const SENSOR_ONBOARD_HUE = '#947C54'; //'#9e77c9'//40; + +export const sensor_mixgo_button_is_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('btn') + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_PRESSED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_IS_PRESSED); + } +}; + +export const sensor_mixgo_button_was_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('btn') + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WAS_PRESSED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_WAS_PRESSED); + } +}; + +export const sensor_mixgo_button_get_presses = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('btn') + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_PRESSES); + this.appendValueInput('VAR') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_GET_PRESSES_TIME); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_BUTTON + Blockly.Msg.MIXLY_GET_PRESSES); + } +}; + +export const sensor_mixgo_button_attachInterrupt = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput("btn") + .appendField(Blockly.Msg.MIXLY_ESP32_INTERRUPT) + .appendField(Blockly.Msg.MIXLY_BUTTON) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RISING, "machine.Pin.IRQ_RISING"], + [Blockly.Msg.MIXLY_FALLING, "machine.Pin.IRQ_FALLING"], + [Blockly.Msg.MIXLY_CHANGE, "(machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING)"] + ]), "mode"); + this.appendValueInput('DO') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_ATTACHINTERRUPT); + } +}; + +export const sensor_mixgocar42_button_is_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BUTTON) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_PRESSED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_IS_PRESSED); + } +}; + +export const sensor_mixgocar42_button_was_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BUTTON) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WAS_PRESSED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_WAS_PRESSED); + } +}; + +export const sensor_mixgocar42_button_get_presses = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_BUTTON) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_PRESSES); + this.appendValueInput('VAR') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_GET_PRESSES_TIME); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_BUTTON + Blockly.Msg.MIXLY_GET_PRESSES); + } +}; + +export const sensor_mixgocar42_button_attachInterrupt = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_INTERRUPT) + .appendField(Blockly.Msg.MIXLY_BUTTON) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RISING, "machine.Pin.IRQ_RISING"], + [Blockly.Msg.MIXLY_FALLING, "machine.Pin.IRQ_FALLING"], + [Blockly.Msg.MIXLY_CHANGE, "(machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING)"] + ]), "mode"); + this.appendValueInput('DO') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_ATTACHINTERRUPT); + } +}; + +export const sensor_mixgo_pin_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput("button") + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_TOUCHED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_sensor_pin_pressed); + } +}; + +export const sensor_mixgoce_pin_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput("button") + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_TOUCHED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_sensor_pin_pressed); + } +}; + +export const sensor_mpython_pin_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput("button") + .appendField(Blockly.Msg.MIXLY_ESP32_TOUCH_SENSOR) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_IS_TOUCHED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_sensor_pin_pressed); + } +}; + +export const sensor_mixgo_touch_slide = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TOUCH_SLIDE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_VALUE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOUCH_SLIDE_TOOLTIP); + } +}; + +export const sensor_distance_hrsc04 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CHAOSHENGBO) + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_CHAOSHENGBO); + } +}; + +// var RTC_TIME_TYPE = [ +// [Blockly.Msg.MIXLY_YEAR, "Year"], +// [Blockly.Msg.MIXLY_MONTH, "Month"], +// [Blockly.Msg.MIXLY_DAY, "Day"], +// [Blockly.Msg.MIXLY_HOUR, "Hour"], +// [Blockly.Msg.MIXLY_MINUTE, "Minute"], +// [Blockly.Msg.MIXLY_SECOND, "Second"], +// [Blockly.Msg.MIXLY_WEEK, "Week"], +// [Blockly.Msg.MIXLY_MIX1, "Mix1"], +// [Blockly.Msg.MIXLY_MIX2, "Mix2"], +// ]; + +export const RTC_set_time = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RTCSETTIME) + .appendField('myRTC'); + this.appendValueInput("hour") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_HOUR); + this.appendValueInput("minute") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_MINUTE); + this.appendValueInput("second") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_SECOND); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(false); + this.setTooltip(Blockly.Msg.MIXLY_RTCSETTIME + Blockly.Msg.MIXLY_MIX2); + } +}; + +export const RTC_set_date = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RTCSETDATE) + .appendField('myRTC'); + this.appendValueInput("year") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_YEAR); + this.appendValueInput("month") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_MONTH); + this.appendValueInput("day") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(" " + Blockly.Msg.MIXLY_DAY); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_RTCSETDATE + Blockly.Msg.MIXLY_MIX1); + } +}; + +export const HCSR04 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_CHAOSHENGBO); + this.appendValueInput("PIN1", Number) + .appendField('Trig #') + .setCheck(Number); + this.appendValueInput("PIN2", Number) + .appendField('Echo #') + .setCheck(Number); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_CHAOSHENGBO); + } +}; + +export const sensor_mixgo_light = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_LIGHT); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ESP32_SENSOR_NIXGO_LIGHT_TOOLTIP); + } +}; + +export const number1 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["1", "touch1"], + ["2", "touch2"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const number2 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["0", "0"], + ["1", "1"], + ["2", "2"], + ["3", "3"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const number3 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_UP, "12"], + [Blockly.Msg.MIXLY_DOWN, "14"], + [Blockly.Msg.MIXLY_LEFT, "13"], + [Blockly.Msg.MIXLY_RIGHT, "15"], + ["A", "32"], ["B", "33"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const number4 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["0", "0"], + ["1", "1"], + ["2", "2"], + ["3", "3"], + ["4", "4"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const number5 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["0", "0"], + ["1", "1"], + ["2", "2"], + ["3", "3"], + ["4", "4"], + ["5", "5"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const number6 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["3", "3"], + ["4", "4"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const number7 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + ["0", "0"], + ["1", "1"] + ]), 'op') + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_INOUT_HIGHLOW); + } +}; + +export const sensor_mixgo_pin_near_single = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_NEAR); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_VALUE); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP + Blockly.Msg.MIXLY_ESP32_NEAR); + } +}; + +export const sensor_mixgo_pin_near_double = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "left"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "right"] + ]), "direction") + .appendField(Blockly.Msg.MIXLY_ESP32_NEAR); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('direction'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + var TOOLTIPS = { + 'left': Blockly.Msg.TEXT_TRIM_LEFT, + 'right': Blockly.Msg.TEXT_TRIM_RIGHT, + }; + return mode0 + TOOLTIPS[mode] + mode1 + }); + } +}; + +export const sensor_mixgo_pin_near = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_ESP32_NEAR); + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.mixpy_PL_TEXT_TOP, "l"], [Blockly.Msg.mixpy_PL_TEXT_BOTTOM, "r"]]), "direction") + this.setOutput(true, Number); + this.setInputsInline(true); + // var thisBlock = this; + // this.setTooltip(function () { + // var mode = thisBlock.getFieldValue('direction'); + // var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + // var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + // var TOOLTIPS = { + // 'l': Blockly.Msg.mixpy_PL_TEXT_TOP, + // 'r': Blockly.Msg.mixpy_PL_TEXT_BOTTOM, + // }; + // return mode0 + TOOLTIPS[mode] + mode1 + // }); + } +}; + +export const sensor_mixgo_nova_pin_near = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "l"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "r"] + ]), "direction") + .appendField(Blockly.Msg.MIXLY_ESP32_NEAR); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('direction'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + var TOOLTIPS = { + 'l': Blockly.Msg.TEXT_TRIM_LEFT, + 'r': Blockly.Msg.TEXT_TRIM_RIGHT, + }; + return mode0 + TOOLTIPS[mode] + mode1 + }); + } +}; + +export const sensor_mixgo_nova_LTR308 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "l"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "r"] + ]), "direction") + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT + Blockly.Msg.MIXLY_DATA); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('direction'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT; + var TOOLTIPS = { + 'l': Blockly.Msg.TEXT_TRIM_LEFT, + 'r': Blockly.Msg.TEXT_TRIM_RIGHT, + }; + return mode0 + TOOLTIPS[mode] + mode1 + }); + } +}; + +export const sensor_mixgo_LTR308 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.mixpy_PL_TEXT_TOP, "l"], [Blockly.Msg.mixpy_PL_TEXT_BOTTOM, "r"]]), "direction") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT + Blockly.Msg.MIXLY_DATA); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_mixgo_sant_color = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_COLOR_SENSOR + Blockly.Msg.MIXLY_DATA); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +//传感器-实时时钟块_获取时间 +export const onboard_RTC_get_time = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField("RTC") + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RTCGETTIME); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_RTC_GET_TIME_TOOLTIP + ' (year, month, mday, hour, minute, second, weekday, yearday)'); + // var thisBlock = this; + // this.setTooltip(function() { + // var mode = thisBlock.getFieldValue('TIME_TYPE'); + // var mode0 = Blockly.Msg.MIXLY_RTCGETTIME; + // var TOOLTIPS = { + // 'Year':Blockly.Msg.MIXLY_YEAR, + // 'Month':Blockly.Msg.MIXLY_MONTH, + // 'Day':Blockly.Msg.MIXLY_DAY, + // 'Hour':Blockly.Msg.MIXLY_HOUR, + // 'Minute':Blockly.Msg.MIXLY_MINUTE, + // 'Second':Blockly.Msg.MIXLY_SECOND, + // 'Week':Blockly.Msg.MIXLY_WEEK, + // 'Mix1':Blockly.Msg.MIXLY_MIX1, + // 'Mix2':Blockly.Msg.MIXLY_MIX2 + // }; + // return mode0 +TOOLTIPS[mode]; + // }); + } +}; + +export const onboard_RTC_get_timestamp = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_RTCGETTIMESTAMP); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_RTC_GET_TIMESTAMP_TOOLTIP); + } +}; + +export const onboard_RTC_timestamp_totuple = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_RTC_TIMESTAMP); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_TO_TUPLE); + this.setInputsInline(true); + this.setOutput(true, Number); + } +}; + +export const onboard_RTC_settime_string = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField('RTC'); + this.appendValueInput('CONTENT') + .appendField(Blockly.Msg.MIXLY_USE_STRING_TUPLE) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RTCSETTIME); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const onboard_RTC_set_datetime = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField("RTC") + this.appendValueInput('year') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_YEAR); + this.appendValueInput('month') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_MONTH); + this.appendValueInput('day') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_DAY); + this.appendValueInput('hour') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_HOUR); + this.appendValueInput('minute') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_MINUTE); + this.appendValueInput('second') + .setCheck(Number) + .appendField(" " + Blockly.Msg.MIXLY_SECOND); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_RTC_SET_DATATIME_TOOLTIP); + } +}; + +export const sensor_rtc_init = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("RTC") + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_SETUP) + .setCheck("var"); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SENSOR_RTC_INT_TOOLTIP); + } +}; + +export const onboard_RTC_get_time_str = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RTC_GET_TIME_STR); + this.setOutput(true, String); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_RTC_GET_TIME_TOOLTIP); + } +}; + +export const onboard_RTC_get_timetuple_to_str = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('CONTENT') + .appendField(Blockly.Msg.MIXLY_GPS_TIME + Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE) + .setCheck() + this.appendDummyInput() + .appendField(Blockly.Msg.A_TO_B + Blockly.Msg.MIXLY_GPS_TIME + Blockly.Msg.LANG_MATH_STRING) + this.setOutput(true, String); + this.setInputsInline(true); + } +}; + +export const sensor_LTR308 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_LIGHT); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ESP32_SENSOR_NIXGO_LIGHT_TOOLTIP); + } +}; + +export const sensor_sound = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_SOUND); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.ESP32_SENSOR_NIXGO_SOUND_TOOLTIP); + } +}; + +export const sensor_aht11 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_TEM_HUM + " ") + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETTEMPERATUE, "temperature"], + [Blockly.Msg.MIXLY_GETHUMIDITY, "humidity"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var TOOLTIPS = { + "temperature": Blockly.Msg.MIXLY_MICROBIT_SENSOR_SHT_temperature_TOOLTIP, + "humidity": Blockly.Msg.MIXLY_ESP32C3_SENSOR_AHT_HUM_TOOLTIP + }; + return TOOLTIPS[mode] + }); + } +}; + +export const sensor_get_temperature = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_hp203 = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_Altitude + Blockly.Msg.MSG.catSensor + " ") + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_GETPRESSURE, "pressure()"], + [Blockly.Msg.MIXLY_GETTEMPERATUE, "temperature()"], + [Blockly.Msg.MIXLY_GET_ALTITUDE, "altitude()"], + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const rfid_readid = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField("RFID" + Blockly.Msg.MIXLY_RFID_READ_CARD); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_RFID_READ_CARD_UID); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const rfid_readcontent = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField("RFID" + Blockly.Msg.MIXLY_RFID_READ_CARD); + this.appendValueInput('SECTOR') + .appendField(Blockly.Msg.MIXLY_LIST_INDEX) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ALL); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const rfid_write = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_RFID_WRITE); + this.appendValueInput('SECTOR') + .appendField(Blockly.Msg.MIXLY_LIST_INDEX) + this.appendValueInput('CONTENT') + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_WRITE_NUM) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const rfid_write_return = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_RFID_WRITE); + this.appendValueInput('SECTOR') + .appendField(Blockly.Msg.MIXLY_LIST_INDEX) + this.appendValueInput('CONTENT') + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_WRITE_NUM) + this.appendDummyInput() + .appendField(Blockly.Msg.RETURN_SUCCESS_OR_NOT); + this.setInputsInline(true); + this.setOutput(true, Boolean); + } +}; + +export const rfid_status = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("RFID") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_RFID_SCAN_OK, "True"], + [Blockly.Msg.MIXLY_RFID_SCAN_NOTAGERR, "None"], + [Blockly.Msg.MIXLY_RFID_SCAN_ERROR, "False"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_get_acceleration = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION) + .appendField(new Blockly.FieldDropdown([ + ["x", "[0]"], + ["y", "[1]"], + ["z", "[2]"], + ["(x,y,z)", ""], + [Blockly.Msg.MIXLY_STRENGTH, "strength"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION1; + var TOOLTIPS = { + '[0]': 'x', + '[1]': 'y', + '[2]': 'z', + '': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_eulerangles = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GET_GESTURE_ALL) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.ME_GO_PITCH, '[0]'], + [Blockly.Msg.ME_GO_ROLL, '[1]'], + [Blockly.Msg.ME_GO_PITCH + ', ' + Blockly.Msg.ME_GO_ROLL, ''] + ]), 'angle'); + + this.appendDummyInput("") + this.setOutput(true, Number); + this.setInputsInline(true); + + } +}; + +export const sensor_onboard_mpu9250_gesture = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT_GESTURE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_shake, "shake"], + [Blockly.Msg.MIXLY_UP, "up"], + [Blockly.Msg.MIXLY_DOWN, "down"], + [Blockly.Msg.MIXLY_LEFT, "left"], + [Blockly.Msg.MIXLY_RIGHT, "right"], + [Blockly.Msg.MIXLY_MICROBIT_face_up, "face up"], + [Blockly.Msg.MIXLY_MICROBIT_face_down, "face down"] + ]), "gesture"); + this.setOutput(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('gesture'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT; + var mode1 = Blockly.Msg.MSG.catSensor; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_STATE; + var mode3 = Blockly.Msg.MIXLY_MICROBIT_PERFORMANCE + var TOOLTIPS = { + 'shake': Blockly.Msg.MIXLY_MICROBIT_shake, + 'up': Blockly.Msg.MIXLY_UP, + 'down': Blockly.Msg.MIXLY_DOWN, + 'left': Blockly.Msg.MIXLY_LEFT, + 'right': Blockly.Msg.MIXLY_RIGHT, + 'face up': Blockly.Msg.MIXLY_MICROBIT_face_up, + 'face down': Blockly.Msg.MIXLY_MICROBIT_face_down, + // 'freefall':Blockly.Msg.MIXLY_MICROBIT_freefall, + // '3g': '3g', + // '6g': '6g', + // '8g': '8g' + }; + return mode0 + mode1 + mode2 + TOOLTIPS[mode] + mode3; + }); + } +}; + +export const sensor_onboard_mpu9250_get_acceleration = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION1; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_onboard_mpu9250_get_magnetic = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_onboard_mpu9250_get_gyro = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_ESP32_SENOR_GYRO) + .appendField(new Blockly.FieldDropdown([ + ["x", "x"], + ["y", "y"], + ["z", "z"], + ["(x,y,z)", "values"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_ESP32_SENOR_GYRO; + var TOOLTIPS = { + 'x': 'x', + 'y': 'y', + 'z': 'z', + '(x,y,z)': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_onboard_mpu9250_calibrate_compass = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS); + } +}; + +export const sensor_onboard_mpu9250_temperature = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE) + this.setOutput(true, Number); + this.setInputsInline(true); + + this.setTooltip(Blockly.Msg.MIXLY_GETTEMPERATUE); + } +}; + +export const sensor_onboard_mpu9250_field_strength = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET_COMPASS) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH, 'strength'], + [Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE, 'heading'] + ]), 'compass'); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('compass'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_JS_GET_COMPASS; + var TOOLTIPS = { + 'strength': Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH, + 'heading': Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE + }; + return mode0 + TOOLTIPS[mode]; + }); + } +}; + +export const sensor_onboard_compass_reset = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField("MPU9250") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_COMPASS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Reset_COMPASS); + } +}; + +//mixgo_cc onboard_sensor blocks: +export const sensor_mixgo_cc_mmc5603_get_magnetic = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH) + .appendField(new Blockly.FieldDropdown([ + ["x", "[0]"], + ["y", "[1]"], + ["z", "[2]"], + ["(x,y,z)", ""], + [Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH_ALL, "all"] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_JS_FIELD_STRENGTH; + var TOOLTIPS = { + '[0]': 'x', + '[1]': 'y', + '[2]': 'z', + '': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_mixgo_cc_mmc5603_get_angle = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET_COMPASS + Blockly.Msg.MIXLY_MICROBIT_JS_BY_ANGLE) + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const sensor_mixgo_cc_mmc5603_calibrate_compass = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_CALIBRATE_COMPASS); + } +}; + +//mixgo_me onboard_sensor blocks: + +export const sensor_mixgome_temperature = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE) + this.appendDummyInput("") + this.setOutput(true, Number); + this.setInputsInline(true); + + } +}; + +//mixgo_ce onboard_sensor blocks: + +export const sensor_mixgoce_temperature = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE) + this.appendDummyInput("") + this.setOutput(true, Number); + this.setInputsInline(true); + + } +}; + +export const sensor_mpython_qmi8658_get_gyro = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_ESP32_SENOR_GYRO) + .appendField(new Blockly.FieldDropdown([ + ["x", "[0]"], + ["y", "[1]"], + ["z", "[2]"], + ["(x,y,z)", ""] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_ESP32_SENOR_GYRO; + var TOOLTIPS = { + '[0]': 'x', + '[1]': 'y', + '[2]': 'z', + '': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_mpython_qmi8658_temperature = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GETTEMPERATUE) + this.setOutput(true, Number); + this.setInputsInline(true); + + this.setTooltip(Blockly.Msg.MIXLY_GETTEMPERATUE); + } +}; + +export const sensor_rm_pin_near_double = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "1"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "2"] + ]), "direction") + .appendField(Blockly.Msg.MIXLY_ESP32_NEAR); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('direction'); + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + var TOOLTIPS = { + 'left': Blockly.Msg.TEXT_TRIM_LEFT, + 'right': Blockly.Msg.TEXT_TRIM_RIGHT, + }; + return mode0 + TOOLTIPS[mode] + mode1 + }); + } +}; + +export const sensor_rm_battery_left = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_CAR_BATTERY_LEFT); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const sensor_rm_acc = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField("acc" + Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_ADXL345_XA, "[0]"], + [Blockly.Msg.MIXLY_ADXL345_YA, "[1]"], + [Blockly.Msg.MIXLY_ACC_SHAKE, "[2]"], + [Blockly.Msg.MIXLY_ADXL345_XA + ',' + Blockly.Msg.MIXLY_ADXL345_YA + ',' + Blockly.Msg.MIXLY_ACC_SHAKE, ""] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_ACCELERATION); + + } +}; + +//car4.2 +export const sensor_mixgocar_pin_near_line = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "[0]"], + [Blockly.Msg.MIXGO_LEFT_MID, "[1]"], + [Blockly.Msg.MIXGO_RIGHT_MID, "[2]"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "[3]"], + [Blockly.Msg.MIXLY_ALL, ""] + ]), "key") + .appendField(Blockly.Msg.MIXGO_LINE_SENSOR_VAL); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(function () { + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + return mode0 + mode1 + }); + } +}; + +export const sensor_mixgocar_pin_near = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXGO_LEFT_FRONT, "[0]"], + [Blockly.Msg.MIXGO_RIGHT_FRONT, "[1]"], + [Blockly.Msg.MIXGO_LEFT_BACK, "[3]"], + [Blockly.Msg.MIXGO_RIGHT_BACK, "[2]"], + [Blockly.Msg.MIXLY_ALL, ""] + ]), "key") + .appendField(Blockly.Msg.MIXGO_PROXIMITY_SENSOR); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(function () { + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + return mode0 + mode1 + }); + } +}; + +export const sensor_mixgocar_pin_near_state_change = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_CAR_SENSOR_ONBOARD_CHANGE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MIXGO_CAR_SENSOR_ONBOARD_AUTO_CHANGE, "AS"], + [Blockly.Msg.MIXLY_MIXGO_CAR_USE_LINE_ONLY, "LP"], + [Blockly.Msg.MIXLY_MIXGO_CAR_USE_PROXIMITY_ONLY, "OA"] + ]), "key"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const sensor_mixgocar_battery_left = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MIXGO_CAR_BATTERY_LEFT); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +//mixbot onboard_sensor below: + +export const sensor_mixbot_patrol_calibrate = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXGO_LINE_SENSOR) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MIXBOT_LINE_SENSOR_CALIBRATE_WHITE, "WHITE"], + [Blockly.Msg.MIXLY_MIXBOT_LINE_SENSOR_CALIBRATE_BLACK, "BLACK"], + [Blockly.Msg.MIXLY_MIXBOT_LINE_SENSOR_CALIBRATE_RESET, "RESET_TO_FAB"] + ]), "key"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + } +}; + +export const sensor_mixbot_patrol_value = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXGO_LEFT_FRONT, "[0]"], + [Blockly.Msg.MIXGO_RIGHT_FRONT, "[1]"], + [Blockly.Msg.MIXGO_LEFT_BACK, "[3]"], + [Blockly.Msg.MIXGO_RIGHT_BACK, "[2]"], + [Blockly.Msg.MIXLY_ALL, ""] + ]), "key") + .appendField(Blockly.Msg.MIXGO_LINE_SENSOR_VAL); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(function () { + var mode0 = Blockly.Msg.MIXLY_ESP32_SENSOR_MIXGO_PIN_NEAR_TOOLTIP; + var mode1 = Blockly.Msg.MIXLY_ESP32_NEAR; + return mode0 + mode1 + }); + } +}; + +export const sensor_mixbot_temperature = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET + Blockly.Msg.MIXLY_MICROBIT_Board_temperature) + this.appendDummyInput("") + this.setOutput(true, Number); + this.setInputsInline(true); + + } +}; + +export const sensor_mixbot_get_gyro = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_ESP32_SENOR_GYRO) + .appendField(new Blockly.FieldDropdown([ + ["x", "[0]"], + ["y", "[1]"], + ["z", "[2]"], + ["(x,y,z)", ""] + ]), "key"); + this.setOutput(true, Number); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('key'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_Direction; + var mode2 = Blockly.Msg.MIXLY_ESP32_SENOR_GYRO; + var TOOLTIPS = { + '[0]': 'x', + '[1]': 'y', + '[2]': 'z', + '': Blockly.Msg.MIXLY_MICROBIT_Shiliang_Direction, + }; + return mode0 + TOOLTIPS[mode] + mode1 + mode2; + }); + } +}; + +export const sensor_bitbot_ALS = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_ESP32_EXTERN_LIGHT) + this.appendValueInput('mode') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LCD_NUMBERING); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_LIGHT_INTENSITY + "(%)"); + this.setOutput(true, Number); + this.setInputsInline(true); + } +}; + +export const bitbot_als_num = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(Profile.default.als_num), 'PIN'); + this.setOutput(true, Number); + } +}; + +export const sensor_button_is_pressed = sensor_mixgo_button_is_pressed; +export const sensor_button_was_pressed = sensor_mixgo_button_was_pressed; +export const sensor_button_get_presses = sensor_mixgo_button_get_presses; +export const sensor_pin_pressed = sensor_mixgo_pin_pressed; +export const sensor_pin_near = sensor_mixgo_pin_near; +export const sensor_light = sensor_mixgo_light; +export const dht11 = sensor_dht11; +export const sensor_field_strength = sensor_mpu9250_field_strength; +export const sensor_temperature = sensor_mpu9250_temperature + +//educore sensor_onboard +export const educore_voice_sensor = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_ESP32_EXTERN_SOUND); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const sensor_read = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GET) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_MICROBIT_JS_I2C_VALUE); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_light_sensor = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LIGHT_SENSOR); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_gyroscope_sensor = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_GYROSCOPE_SENSOR); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_gyroscope_sensor_read = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GET) + .setCheck("var"); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_Horizontal_inclination, "X"], + ["y", "[1]"], + ["z", "[2]"] + ]), "key"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_gyroscope_sensor_shake = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_GET) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_BE_SHAKED) + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const educore_button_sensor = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_BUTTON) + .appendField(new Blockly.FieldDropdown([ + ["a", "a"], + ["b", "b"], + ["c", "c"] + ]), "btn"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_button_was_pressed = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_BUTTON); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WAS_PRESSED); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SENOR_WAS_PRESSED); + } +}; + +export const educore_rfid_sensor = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput("PIN") + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_RFID_INITIAL); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_rfid_sensor_scan = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput("SUB") + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_RFID_READ); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const educore_rfid_sensor_scan_data = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendValueInput("SUB") + .appendField(Blockly.Msg.MIXLY_COMMUNICATION_RFID_READ + Blockly.Msg.MIXLY_COMMUNICATION_DATA_FROM); + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_GET) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SERIAL_NUMBER, "serial_number"] + ]), "key"); + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const sensor_get_the_coprocessor_version = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_THE_COPROCESSOR_VERSION) + this.setOutput(true); + this.setInputsInline(true); + } +}; + +export const simulated_light_sensor = { + init: function () { + this.setColour(SENSOR_ONBOARD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.ANALOG + Blockly.Msg.MIXLY_LIGHT_SENSOR2) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.TEXT_TRIM_LEFT, "0"], + [Blockly.Msg.TEXT_TRIM_RIGHT, "1"] + ]),"key"); + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_set_of + Blockly.Msg.MIXLY_MICROBIT_JS_SYSTEM_RAISE_VALUE); + this.setOutput(true); + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/serial.js b/mixly/boards/default_src/micropython/blocks/serial.js new file mode 100644 index 00000000..c7b065f5 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/serial.js @@ -0,0 +1,426 @@ +import * as Blockly from 'blockly/core'; + +const SERIAL_HUE = 65; //'#58a8de'//65; + +export const serial_print_byte = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("CONTENT", String) + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_SERIAL_WRITE + '(' + Blockly.Msg.LANG_MATH_BYTE + ')'); + //this.setFieldValue('1','mode') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.TEXT_PRINT_TOOLTIP); + } +}; + +export const serial_print = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("CONTENT", String) + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINT); + //this.setFieldValue('1','mode') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.TEXT_PRINT_TOOLTIP); + } +}; + +export const serial_println = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("CONTENT", String) + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINTLN); + //this.setFieldValue('1','mode') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.TEXT_PRINT_Huanhang_TOOLTIP + Blockly.Msg.TEXT_PRINT_TOOLTIP); + } +}; + +//打印16进制数 +export const serial_print_hex = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINTLN); + this.appendValueInput("CONTENT", Number) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MATH_BIN, "bin"], + [Blockly.Msg.MATH_OCT, "oct"], + [Blockly.Msg.MATH_DEC, "int"], + [Blockly.Msg.MATH_HEX, "hex"] + ]), "STAT") + .setCheck(Number); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setFieldValue('hex', 'STAT') + this.setTooltip(Blockly.Msg.TEXT_PRINT_HEX_TOOLTIP); + } +}; + +export const serial_receive_data_event = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput('char_marker') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_SERIAL_WHEN_CONTAIN_DATA) + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + } +}; + +export const serial_readstr = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_SERIAL_READSTR); + //this.setFieldValue('1','mode') + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_BLOCKGROUP_SERIAL_READ_STR); + } +}; + +export const serial_any = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_SERIAL_AVAILABLE); + //this.setFieldValue('1','mode') + this.setOutput(true, Boolean); + this.setTooltip(Blockly.Msg.MIXLY_SERIAL_AVAILABLE1); + } +}; + +export const serial_readline = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_ESP32_READ_LINE); + //this.setFieldValue('1','mode') + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_JS_SERIAL_READ_LINE1); + } +}; + +export const serial_readstr_until = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField("Serial " + Blockly.Msg.MIXLY_SERIAL_READSTR_UNTIL) + .appendField(new Blockly.FieldDropdown([ + ["new line", "serial.delimiters(Delimiters.NewLine)"], + [",", "serial.delimiters(Delimiters.Comma)"], + ["$", "serial.delimiters(Delimiters.Dollar)"], + [":", "serial.delimiters(Delimiters.Colon)"], + [".", "serial.delimiters(Delimiters.Fullstop)"], + ["#", "serial.delimiters(Delimiters.Hash)"] + ]), "char_marker"); + + this.setInputsInline(true); + this.setOutput(true, String); + } +}; + +export const serial_softserial_new = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("RX") + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField("RX#") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendValueInput("TX") + .appendField("TX#") + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SERIAL_BEGIN) + .appendField(new Blockly.FieldDropdown([ + ['115200', '115200'], + ['57600', '57600'], + ['37400', '38400'], + ['31250', '31250'], + ['28800', '28800'], + ['19200', '19200'], + ['14400', '14400'], + ['9600', '9600'], + ['4800', '4800'], + ['2400', '2400'], + ['1200', '1200'], + ['300', '300'] + ]), 'baudrate'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SERIAL_softserial); + } +}; + +export const serial_softserial = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP) + .appendField(new Blockly.FieldDropdown([ + ['uart1 (RX=23,TX=19)', '1'], + ['uart2 (RX=5,TX=18)', '2'] + ]), 'mode'); + //this.setFieldValue('1','mode') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SERIAL_BEGIN) + .appendField(new Blockly.FieldDropdown([ + ['115200', '115200'], + ['57600', '57600'], + ['37400', '38400'], + ['31250', '31250'], + ['28800', '28800'], + ['19200', '19200'], + ['14400', '14400'], + ['9600', '9600'], + ['4800', '4800'], + ['2400', '2400'], + ['1200', '1200'], + ['300', '300'] + ]), 'baudrate'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_SERIAL_softserial); + } +}; + +export const serial_begin = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField("Serial " + Blockly.Msg.MIXLY_SERIAL_BEGIN) + .appendField(new Blockly.FieldDropdown([ + ['115200', '115200'], + ['57600', '57600'], + ['37400', '38400'], + ['31250', '31250'], + ['28800', '28800'], + ['19200', '19200'], + ['14400', '14400'], + ['9600', '9600'], + ['4800', '4800'], + ['2400', '2400'], + ['1200', '1200'], + ['300', '300'] + ]), 'baudrate'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_SET + Blockly.Msg.MIXLY_SERIAL_BEGIN); + } +}; + +export const system_input = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.blockpy_inout_raw_input) + .setCheck(String); + this.setOutput(true); + this.setTooltip(Blockly.Msg.INOUT_input_TOOLTIP); + } +}; + +export const system_print = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINTLN); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.BLOCKPY_PRINT_TOOLTIP); + } +}; + +export const system_print_inline = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINT); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.TEXT_PRINT_TOOLTIP); + } +}; + +export const system_print_end = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINT); + this.appendValueInput("END") + .appendField(Blockly.Msg.MIXLY_ENDSWITH); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_INOUT_PRINT_END_TOOLTIP); + } +}; + +export const system_print_many = { + init: function () { + this.setColour(SERIAL_HUE); + this.itemCount_ = 2; + this.updateShape_(); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setInputsInline(true); + this.setMutator(new Blockly.icons.MutatorIcon(['system_print_item'], this)); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_INOUT_PRINT_MANY_TOOLTIP); + }, + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('system_print_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('system_print_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i) + .connection.connect(connections[i]); + } + } + }, + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.MIXLY_MIXPY_INOUT_PRINT_EMPTY); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.MIXLY_SERIAL_PRINTLN); + } + } + } + } +}; + +export const system_print_container = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SERIAL_PRINTLN); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_INOUT_PRINT_MANY_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const system_print_item = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_INOUT_PRINT_MANY_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const serial_send_to_ai = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendValueInput("CONTENT") + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_EMQX_PUBLISH); + this.appendDummyInput() + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_TO + Blockly.Msg.MIXLY_OTHER + 'MP' + Blockly.Msg.MIXLY_DEVICE) + .appendField(Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_TITLE_REPEAT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_TRUE, 'True'], + [Blockly.Msg.MIXLY_TURTLE_WRITE_MOVE_FALSE, 'False'] + ]), 'STAT') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const serial_read_from_ai = { + init: function () { + this.setColour(SERIAL_HUE); + this.appendDummyInput() + .appendField("Serial") + .appendField(new Blockly.FieldDropdown([['uart1', '1']]), 'mode') + .appendField(Blockly.Msg.MIXLY_ESP32_READ + Blockly.Msg.MIXLY_OTHER + 'MP' + Blockly.Msg.MIXLY_DEVICE + Blockly.Msg.MIXLY_SD_DATA); + this.setOutput(true, Boolean); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/system.js b/mixly/boards/default_src/micropython/blocks/system.js new file mode 100644 index 00000000..f1febe27 --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/system.js @@ -0,0 +1,289 @@ +import * as Blockly from 'blockly/core'; + + +const SYSTEM_HUE = 120; //'#EB8045'; + +export const controls_delay_new = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DELAY) + this.appendValueInput("DELAY_TIME", Number) + .setCheck(Number); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SECOND, "s"], + [Blockly.Msg.MIXLY_mSecond, "ms"], + [Blockly.Msg.MIXLY_uSecond, "us"] + ]), 'Time'); + this.setFieldValue('s', 'Time') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_DELAY); + } +}; + +export const controls_delay = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DELAY) + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_SECOND, "s"], + [Blockly.Msg.MIXLY_mSecond, "ms"], + [Blockly.Msg.MIXLY_uSecond, "us"] + ]), 'Time'); + this.appendValueInput("DELAY_TIME", Number) + .setCheck(Number); + this.setFieldValue('ms', 'Time') + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_DELAY); + } +}; + +export const Panic_with_status_code = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendValueInput("STATUS_CODE", Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_Panic_with_status_code) + .setCheck(Number); + this.setPreviousStatement(true, null); + // this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Panic_with_status_code); + } +}; + +export const reset = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_Reset_micro); + this.setPreviousStatement(true); + // this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_Reset_micro); + } +}; + +export const controls_millis = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_RUNTIME); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_mSecond, "ms"], + [Blockly.Msg.MIXLY_uSecond, "us"] + ]), 'Time'); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_CONTROLS_MILLIS_TOOLTIP); + } +}; + +export const raw_block = { + // Container. + init: function () { + this.setColour(SYSTEM_HUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendDummyInput() + .appendField('Code Block:'); + this.appendDummyInput() + .appendField(new Blockly.FieldMultilineInput('12345'), 'TEXT'); + } +}; + +export const controls_uname = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_UNAME); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_UNAME); + } +}; + +export const timer = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendValueInput('VAR') + .appendField("Timer") + .setCheck("var"); + this.appendValueInput('period') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + // .appendField("Timer") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_PERIOD_MIL); + this.appendValueInput('mode') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE); + this.appendValueInput('callback') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO); + // this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_TIMER_TOOLTIP); + } +}; + +export const system_ticks_diff = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendValueInput('END') + // .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_ESP32_TIME_TICKS_DIFF); + this.appendValueInput('START') + // .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_ESP32_TIME_MINUS); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SYSTEM_TICKS_DIFF_TOOLTIP); + } +}; + +export const set_system_timer = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendValueInput('VAR') + .appendField("Timer") + .setCheck("var") + .appendField(Blockly.Msg.MIXLY_SETUP); + this.appendValueInput("PIN") + .appendField("ID") + .setCheck(Number); + this.appendValueInput("period") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_PERIOD_MIL) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_mSecond) + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PYTHON_ONE_SHOT, "ONE_SHOT"], + [Blockly.Msg.MIXLY_PYTHON_PERIODIC, "PERIODIC"] + ]), "mode"); + this.appendValueInput('callback') + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SYSTEM_TIMER_TOOLTIP); + } +}; + +export const system_timer_init = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendValueInput('VAR') + .appendField("Timer") + .setCheck("var"); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_RESTART); + this.appendValueInput("period") + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_PERIOD_MIL) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_mSecond) + .appendField(Blockly.Msg.MIXLY_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PYTHON_ONE_SHOT, "ONE_SHOT"], + [Blockly.Msg.MIXLY_PYTHON_PERIODIC, "PERIODIC"] + ]), "mode"); + this.appendValueInput('callback') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_DO) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_ESP32_SYSTEM_TIMER_TOOLTIP); + } +}; + +export const system_timer_deinit = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendValueInput('VAR') + .appendField("Timer") + .setCheck("var"); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STOP); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + } +}; + +export const system_wdt_init = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MACHINE_WDT) + .appendField(Blockly.Msg.MIXLY_SETUP) + this.appendValueInput('period') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_MACHINE_WDT_TIMEOUT) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_mSecond) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_MACHINE_WDT_INIT_TOOLTIP); + } +}; + +export const system_wdt_feed = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MACHINE_WDT) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MACHINE_FEED) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_MACHINE_WDT_FEED_TOOLTIP); + } +}; + +export const system_machine_reset = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MACHINE_RESET) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MIXLY_MACHINE_RESET_TOOLTIP); + } +}; + +export const system_bitbot_shutdown = { + init: function () { + this.setColour(SYSTEM_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.BITBOT) + this.appendDummyInput("") + .appendField(Blockly.Msg.SHUTDOWN) + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.MICROPYTHON_BITBOT_SHUTDOWN_TOOLTIP); + } +}; + +export const Timer_init = system_timer_init; +export const system_timer = system_timer_init; +export const timer2 = system_timer_init; +export const time_ticks_diff = system_ticks_diff; +export const base_delay = controls_delay; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/blocks/weather.js b/mixly/boards/default_src/micropython/blocks/weather.js new file mode 100644 index 00000000..69599c1c --- /dev/null +++ b/mixly/boards/default_src/micropython/blocks/weather.js @@ -0,0 +1,368 @@ +import * as Blockly from 'blockly/core'; + +const WEATHER_HUE = '#27b6ac'; + +export const WEATHER_NOW = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MSG.catweather) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW, "weather_now"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_ALARM, "weather_alarm"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_AIR_NOW, "air_now"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_TIDE_DAILY, "tide_daily"], + [Blockly.Msg.MIXLY_WEB_PLACE + Blockly.Msg.HTML_SEARCH, "location_search"] + ]), "mode"); + this.appendValueInput('key') + .appendField(Blockly.Msg.MIXLY_API_PRIVATE_KEY); + this.appendValueInput('addr') + .appendField(Blockly.Msg.MIXLY_GEOGRAPHIC_LOCATION); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const WEATHER_DAILY = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MSG.catweather) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_DAILY, "weather_daily"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_LIFE_SUGGESTION, "life_suggestion"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_AIR_DAILY, "air_daily"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_GEO_SUN, "geo_sun"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_GEO_MOON, "geo_moon"] + ]), "mode"); + this.appendValueInput('key') + .appendField(Blockly.Msg.MIXLY_API_PRIVATE_KEY); + this.appendValueInput('addr') + .appendField(Blockly.Msg.MIXLY_GEOGRAPHIC_LOCATION); + this.appendValueInput('day') + .appendField(Blockly.Msg.MIXLY_WEB_DAILY); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const WEATHER_HOUR = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MSG.catweather) + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_HOURS); + this.appendValueInput('key') + .appendField(Blockly.Msg.MIXLY_API_PRIVATE_KEY); + this.appendValueInput('addr') + .appendField(Blockly.Msg.MIXLY_GEOGRAPHIC_LOCATION); + this.appendValueInput('hour') + .appendField(Blockly.Msg.MIXLY_WEB_HOURS); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Weather_now = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MSG.catweather) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW, "Weather_now"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_ALARM, "Weather_alarm"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_AIR_NOW, "Air_now"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_TIDE_DAILY, "Tide_daily"], + [Blockly.Msg.MIXLY_WEB_PLACE + Blockly.Msg.HTML_SEARCH, "Location_search"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_LIFE_SUGGESTION, "Life_suggestion"] + ]), "mode"); + this.appendValueInput('key') + .appendField(Blockly.Msg.MIXLY_API_PRIVATE_KEY); + this.appendValueInput('addr') + .appendField(Blockly.Msg.MIXLY_GEOGRAPHIC_LOCATION); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const Weather_now_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_WEATHER_PHENOMENON, "text"], + [Blockly.Msg.MIXLY_WEATHER_PHENOMENON_CODE, "code"], + [Blockly.Msg.MIXLY_TEMPERATURE + Blockly.Msg.MIXLY_TEMPERATURE_UNIT_, "temperature"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_FEEL, "feels_like"], + [Blockly.Msg.MIXLY_Altitude + Blockly.Msg.MIXLY_PRESSURE_UNIT, "pressure"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_HUMIDITY, "humidity"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_VISIBILITY, "visibility"], + [Blockly.Msg.ForecastFx, "wind_direction"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_WIND_DIRECT_DEGREE, "wind_direction_degree"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_WIND_SPEED, "wind_speed"], + [Blockly.Msg.MIXLY_WIND_RATING, "wind_scale"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_CLOUDS, "clouds"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Air_now_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_AIR_NOW + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_AIR_NOW_AIRQUAILTY, "api"], + [Blockly.Msg.MIXLY_AIR_NOW_PM25, "pm25"], + [Blockly.Msg.MIXLY_AIR_NOW_PM10, "pm10"], + [Blockly.Msg.MIXLY_AIR_NOW_so2, "so2"], + [Blockly.Msg.MIXLY_AIR_NOW_no2, "no2"], + [Blockly.Msg.MIXLY_AIR_NOW_co, "co"], + [Blockly.Msg.MIXLY_AIR_NOW_o3, "o3"], + [Blockly.Msg.MIXLY_AIR_NOW_pp, "primary_pollutant"], + [Blockly.Msg.MIXLY_AIR_NOW_quailty, "quality"], + [Blockly.Msg.MIXLY_AIR_NOW_last_update, "last_update"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Weather_alarm_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_ALARM + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_WEATHER_ALARM_TITLE, "title"], + [Blockly.Msg.MIXLY_WEATHER_ALARM_TYPE, "type"], + [Blockly.Msg.MIXLY_WEATHER_ALARM_LEVEL, "level"], + [Blockly.Msg.MIXLY_WEATHER_ALARM_DESCRIPTION, "description"], + [Blockly.Msg.MIXLY_WEATHER_ALARM_PUB_DATE, "pub_date"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Life_suggestion_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_LIFE_SUGGESTION + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_AC, "ac"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_AP, "air_pollution"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_AIRING, "airing"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_ALLERGY, "allergy"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_BEER, "beer"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_BOATING, "boating"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_CAR_WS, "car_washing"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_CHILL, "chill"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_COMFORT, "comfort"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_DATING, "dating"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_DRESSING, "dressing"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_FISHING, "fishing"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_FLU, "flu"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_HAIR_DRESS, "hair_dressing"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_KITEFLYING, "kiteflying"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_MAKEUP, "makeup"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_MOOD, "mood"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_MORNINIG_SPORT, "morning_sport"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_NIGHT_LIFE, "night_life"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_ROAD_CONDI, "road_condition"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_SHOPPING, "shopping"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_SPORT, "sport"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_SUNSCREEN, "sunscreen"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_TRAFFIC, "traffic"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_TRAVEL, "travel"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_UMBRELLA, "umbrella"], + [Blockly.Msg.MIXLY_LIFE_SUGGESTION_UV, "uv"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Tide_daily_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_TIDE_DAILY + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_GPS_DATE, "date"], + [Blockly.Msg.MIXLY_TIDE_DAILY_HEIGHT, "tide"], + [Blockly.Msg.MIXLY_TIDE_DAILY_0_TIME, "0,time"], + [Blockly.Msg.MIXLY_TIDE_DAILY_0_HEIGHT, "0,height"], + [Blockly.Msg.MIXLY_TIDE_DAILY_1_TIME, "1,time"], + [Blockly.Msg.MIXLY_TIDE_DAILY_1_HEIGHT, "1,height"], + [Blockly.Msg.MIXLY_TIDE_DAILY_2_TIME, "2,time"], + [Blockly.Msg.MIXLY_TIDE_DAILY_2_HEIGHT, "2,height"], + [Blockly.Msg.MIXLY_TIDE_DAILY_3_TIME, "3,time"], + [Blockly.Msg.MIXLY_TIDE_DAILY_3_HEIGHT, "3,height"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Location_search_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_PLACE + Blockly.Msg.HTML_SEARCH + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_LOCATION_SEARCH_ID, "id"], + [Blockly.Msg.MIXLY_LOCATION_SEARCH_NAME, "name"], + [Blockly.Msg.MIXLY_LOCATION_SEARCH_COUNTRY, "country"], + [Blockly.Msg.MIXLY_LOCATION_SEARCH_PATH, "path"], + [Blockly.Msg.MIXLY_LOCATION_SEARCH_TIMEZONE, "timezone"], + [Blockly.Msg.MIXLY_LOCATION_SEARCH_TIMEZONE_O, "timezone_offset"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Weather_daily = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MSG.catweather) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_DAILY, "Weather_daily"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_AIR_DAILY, "Air_daily"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_GEO_SUN, "Geo_sun"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_GEO_MOON, "Geo_moon"] + ]), "mode"); + this.appendValueInput('key') + .appendField(Blockly.Msg.MIXLY_API_PRIVATE_KEY); + this.appendValueInput('addr') + .appendField(Blockly.Msg.MIXLY_GEOGRAPHIC_LOCATION); + this.appendValueInput('day') + .appendField(Blockly.Msg.MIXLY_WEB_DAILY); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const Weather_daily_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_DAILY); + this.appendValueInput('day') + .appendField(Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_DAILY_DAY + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_GPS_DATE, "date"], + [Blockly.Msg.MIXLY_DAYTIME_WEATHER_PHENOMENON, "text_day"], + [Blockly.Msg.MIXLY_DAYTIME_WEATHER_PHENOMENON_CODE, "code_day"], + [Blockly.Msg.MIXLY_EVENING_WEATHER_PHENOMENON, "text_night"], + [Blockly.Msg.MIXLY_EVENING_WEATHER_PHENOMENON_CODE, "code_night"], + [Blockly.Msg.ForecastHigh + Blockly.Msg.MIXLY_TEMPERATURE_UNIT_, "high"], + [Blockly.Msg.ForecastLow + Blockly.Msg.MIXLY_TEMPERATURE_UNIT_, "low"], + [Blockly.Msg.MIXLY_PROBABILITY_OF_PRECIPITATION, "precip"], + [Blockly.Msg.ForecastFx, "wind_direction"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_WIND_DIRECT_DEGREE, "wind_direction_degree"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_WIND_SPEED, "wind_speed"], + [Blockly.Msg.MIXLY_WIND_RATING, "wind_scale"], + [Blockly.Msg.MIXLY_RAINFALL, "rainfall"], + [Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_NOW_HUMIDITY, "humidity"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Air_daily_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_AIR_DAILY); + this.appendValueInput('day') + .appendField(Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_DAILY_DAY + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_AIR_NOW_AIRQUAILTY, "api"], + [Blockly.Msg.MIXLY_AIR_NOW_PM25, "pm25"], + [Blockly.Msg.MIXLY_AIR_NOW_PM10, "pm10"], + [Blockly.Msg.MIXLY_AIR_NOW_so2, "so2"], + [Blockly.Msg.MIXLY_AIR_NOW_no2, "no2"], + [Blockly.Msg.MIXLY_AIR_NOW_co, "co"], + [Blockly.Msg.MIXLY_AIR_NOW_o3, "o3"], + [Blockly.Msg.MIXLY_AIR_NOW_quailty, "quality"], + [Blockly.Msg.MIXLY_GPS_DATE, "date"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Geo_sun_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_GEO_SUN); + this.appendValueInput('day') + .appendField(Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_DAILY_DAY + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_GPS_DATE, "date"], + [Blockly.Msg.MIXLY_SUNRISE_T, "sunrise"], + [Blockly.Msg.MIXLY_SUNSET_T, "sunset"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const Geo_moon_content = { + init: function () { + this.setColour(WEATHER_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_GEO_MOON); + this.appendValueInput('day') + .appendField(Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_WEB_DATA_SENIVERSE_GET_WEATHER_DAILY_DAY + Blockly.Msg.MIXLY_BELONG); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PARAMETER_FREE, "none"], + [Blockly.Msg.MIXLY_GPS_DATE, "date"], + [Blockly.Msg.MIXLT_MOONRISE_T, "rise"], + [Blockly.Msg.MIXLY_MOONSET_T, "set"], + [Blockly.Msg.MIXLY_MOON_FRACTION, "fraction"], + [Blockly.Msg.MIXLY_MOON_PHASE, "phase"], + [Blockly.Msg.MIXLY_MOON_PHASE_NAME, "phase_name"] + ]), "content"); + this.setInputsInline(true); + this.setOutput(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/converters/actuator.js b/mixly/boards/default_src/micropython/converters/actuator.js new file mode 100644 index 00000000..67268f3c --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/actuator.js @@ -0,0 +1,478 @@ + +'use strict'; + +pbc.moduleFunctionD.get('servo')['servo_write_angle'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var pwmAstName = args[0]._astname; + pbc.pinType="pins_pwm_pin"; + var pinblock; + + if (pwmAstName === "Num") { + pinblock=py2block.convert(args[0]) + } + pbc.pinType=null; + var angleblock=py2block.convert(args[1]); + + return [block("servo_move", func.lineno, {}, { + "PIN":pinblock, + "DEGREE": angleblock, + + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('mixgo.led1')['setonoff'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="number"; + var ledblock = { + _astname: "Num", + n: { + 'v': "1" + } + } + var mode = py2block.convert(ledblock); + pbc.pinType=null; + pbc.inScope="ledswitch"; + var argblock = py2block.convert(args[0]); + + pbc.inScope=null; + return [block("actuator_led_bright", func.lineno, { + + }, { + 'led': mode, + 'bright':argblock, + }, { + "inline": "true" + }), + ]; +} + +pbc.moduleFunctionD.get('mixgo.led2')['setonoff'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="number"; + var ledblock = { + _astname: "Num", + n: { + 'v': "2" + } + } + var mode = py2block.convert(ledblock); + pbc.pinType=null; + pbc.inScope="ledswitch"; + var argblock = py2block.convert(args[0]); + + pbc.inScope=null; + return [block("actuator_led_bright", func.lineno, { + + }, { + 'led': mode, + 'bright':argblock, + }, { + "inline": "true" + }), + ]; +} + +pbc.moduleFunctionD.get('mixgo.led1')['getonoff'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="number"; + var ledblock = { + _astname: "Num", + n: { + 'v': "1" + } + } + var mode = py2block.convert(ledblock); + pbc.pinType=null; + return block("actuator_get_led_bright", func.lineno, { + }, { + 'led': mode, + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('mixgo.led2')['getonoff'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="number"; + var ledblock = { + _astname: "Num", + n: { + 'v': "2" + } + } + var mode = py2block.convert(ledblock); + pbc.pinType=null; + return block("actuator_get_led_bright", func.lineno, { + }, { + 'led': mode, + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('mixgo.led1')['setbrightness'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="number"; + var ledblock = { + _astname: "Num", + n: { + 'v': "1" + } + } + var mode = py2block.convert(ledblock); + pbc.pinType=null; + var brightblock = py2block.convert(args[0]); + + return [block("actuator_led_brightness", func.lineno, {}, { + 'led': mode, + 'bright':brightblock, + }, { + "inline": "true" + }), + ]; +} + +pbc.moduleFunctionD.get('mixgo.led2')['setbrightness'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="number"; + var ledblock = { + _astname: "Num", + n: { + 'v': "2" + } + } + var mode = py2block.convert(ledblock); + pbc.pinType=null; + var brightblock = py2block.convert(args[0]); + + return [block("actuator_led_brightness", func.lineno, {}, { + 'led': mode, + 'bright':brightblock, + }, { + "inline": "true" + }), + ]; +} + + +pbc.moduleFunctionD.get('music')['pitch'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!==1 && args.length!==2){ + throw new Error("Incorrect number of arguments"); + } + + if (args.length === 2) { + pbc.pinType = "pins_pwm_pin"; + var pinblock = py2block.convert(args[0]); + pbc.pinType=null; + pbc.pinType = "pins_tone_notes"; + var pitchblock = py2block.convert(args[1]); + pbc.pinType=null; + + + return [block("esp32_music_pitch", func.lineno, {}, { + 'pitch': pitchblock, + 'PIN': pinblock, + }, { + "inline": "true" + })]; + } + else if (args.length=== 1){ + pbc.pinType = "pins_tone_notes"; + var pitchblock = py2block.convert(args[0]); + pbc.pinType=null; + return [block("esp32_onboard_music_pitch", func.lineno, {}, { + 'pitch': pitchblock, + }, { + "inline": "true" + })]; + + } + +} + +pbc.moduleFunctionD.get('music')['pitch_time'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!==2 && args.length!==3){ + throw new Error("Incorrect number of arguments"); + } + + if (args.length === 2) { + pbc.pinType = "pins_tone_notes"; + var pitchblock = py2block.convert(args[0]); + pbc.pinType=null; + var timeblock=py2block.convert(args[1]); + return [block("esp32_onboard_music_pitch_with_time", func.lineno, {}, { + 'pitch': pitchblock, + "time":timeblock + }, { + "inline": "true" + })]; + } + else if (args.length=== 3){ + pbc.pinType = "pins_pwm_pin"; + var pinblock = py2block.convert(args[0]); + pbc.pinType=null; + pbc.pinType = "pins_tone_notes"; + var pitchblock = py2block.convert(args[1]); + pbc.pinType=null; + var timeblock=py2block.convert(args[2]); + return [block("esp32_music_pitch_with_time", func.lineno, {}, { + 'pitch': pitchblock, + 'PIN': pinblock, + "time":timeblock + }, { + "inline": "true" + })]; + + } + +} + + +pbc.moduleFunctionD.get('music')['stop'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1 && args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + if (args.length == 1){ + pbc.pinType = "pins_pwm_pin"; + var argblock = py2block.convert(args[0]); + pbc.pinType = null; + return [block("esp32_music_stop", func.lineno, {}, { + 'PIN': argblock + }, { + "inline": "true" + })]; + } + if (args.length == 0){ + return [block("esp32_onboard_music_stop", func.lineno, {}, {}, { + "inline": "true" + })]; + } + +} + + +pbc.moduleFunctionD.get('music')['play'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2 && args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + if(args.length == 2){ + pbc.pinType = "pins_playlist_pin"; + var nameblock= py2block.convert(args[0]); + pbc.pinType = "pins_pwm_pin"; + var argblock = py2block.convert(args[1]); + pbc.pinType = null; + return [block("esp32_music_play_list", func.lineno, {}, { + "LIST":nameblock, + 'PIN': argblock + }, { + "inline": "true" + })]; + } + if(args.length == 1){ + pbc.pinType = "pins_playlist_pin"; + var nameblock= py2block.convert(args[0]); + pbc.pinType = null; + return [block("esp32_onboard_music_play_list", func.lineno, {}, { + "LIST":nameblock, + }, { + "inline": "true" + })]; + } +} + +pbc.moduleFunctionD.get('music')['play_show'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType = "pins_playlist_pin"; + var nameblock= py2block.convert(args[0]); + pbc.pinType = "pins_pwm_pin"; + var argblock = py2block.convert(args[1]); + pbc.pinType = null; + return [block("esp32_mixgo_music_play_list_show", func.lineno, {}, { + "LIST":nameblock, + 'PIN': argblock + }, { + "inline": "true" + })]; +} + + + + +pbc.assignD.get('Rgb')['check_assign'] = function(py2block, node, targets, value) { + var funcName = py2block.identifier(value.func.attr); + var moduleName=py2block.identifier(value.func.value.id); + if(value._astname === "Call" && moduleName === "neopixel" + && funcName === "NeoPixel" && value.args.length === 2&&value.keywords.length===1) + return true; + + return false; +} + + +pbc.assignD.get('Rgb')['create_block'] = function(py2block, node, targets, value){ + + var rgbblock=py2block.convert(targets[0]); + pbc.inScope = "rgb_create_block"; + pbc.pinType = "pins_digital_pin"; + // value.args[0].args[0].n.v='pin'+value.args[0].args[0].n.v + var pinblock = py2block.convert(value.args[0].args[0]); + pbc.inScope = null; + pbc.pinType = null; + var countblock = py2block.convert(value.args[1]); + + return block("actuator_neopixel_init", node.lineno, {}, { + "SUB":rgbblock, + "PIN":pinblock, + "LEDCOUNT":countblock + }); +} + + +pbc.moduleFunctionD.get('rgb')['write'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if(args.length!=0){ + throw new Error("Incorrect number of arguments"); + } + + var rgbblock=py2block.convert(func.value); + + return [block("actuator_neopixel_write", func.lineno, {}, { 'SUB':rgbblock, + }, { + "inline": "true" + })]; +} + + + +pbc.moduleFunctionD.get('music')['get_tempo'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if(args.length!=0){ + throw new Error("Incorrect number of arguments"); + } + + return block("esp32_music_get_tempo", func.lineno, {}, { + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('music')['set_tempo'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if(args.length!=2){ + throw new Error("Incorrect number of arguments"); + } + var resoblock=py2block.convert(args[0]); + var speedblock=py2block.convert(args[1]); + + return [block("esp32_music_set_tempo", func.lineno, {}, { + 'TICKS':resoblock, + "BPM":speedblock, + }, { + "inline": "true" + })]; +} +pbc.moduleFunctionD.get('music')['reset'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if(args.length!=0){ + throw new Error("Incorrect number of arguments"); + } + + return [block("esp32_music_reset", func.lineno, {}, { + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('setonoff')['led'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="led" && mac==="mixgo"){ + + pbc.pinType = "pins_pwm_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + pbc.inScope="ledswitch"; + var mode = py2block.convert(args[0]); + pbc.inScope=null; + + return [block("actuator_extern_led_bright", func.lineno, {}, { + "PIN": pinblock, + 'bright':mode + }, { + "inline": "true" + })]; +} + +} + +pbc.objectFunctionD.get('getonoff')['led'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="led" && mac==="mixgo"){ + + pbc.pinType = "pins_pwm_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + + return block("actuator_extern_get_led_bright", func.lineno, {}, { + "PIN": pinblock, + }, { + "inline": "true" + }); +} + +} + +pbc.objectFunctionD.get('setbrightness')['led'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="led" && mac==="mixgo"){ + + pbc.pinType = "pins_pwm_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + var mode = py2block.convert(args[0]); + + return [block("actuator_extern_led_brightness", func.lineno, {}, { + "PIN": pinblock, + 'bright':mode + }, { + "inline": "true" + })]; +} + +} + +pbc.moduleFunctionD.get('mixgo.rgb')['write'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if(args.length!=0){ + throw new Error("Incorrect number of arguments"); + } + + return [block("actuator_onboard_neopixel_write", func.lineno, {}, { + }, { + "inline": "true" + })]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/converters/communicate.js b/mixly/boards/default_src/micropython/converters/communicate.js new file mode 100644 index 00000000..dd8542a2 --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/communicate.js @@ -0,0 +1,441 @@ +var spiClass = 'machine.SPI'; +var i2cClass = 'machine.I2C'; +var owClass = 'onewire.OneWire'; +pbc.assignD.get('I2C')['check_assign'] = function(py2block, node, targets, value) { + var funcName = py2block.identifier(value.func.attr); + var moduleName = py2block.Name_str(value.func.value); + if(value._astname === "Call" && moduleName === "machine" + && funcName === "I2C" && value.keywords.length === 3) + return true; + return false; +} + +pbc.assignD.get('I2C')['create_block'] = function(py2block, node, targets, value){ + + var astname = value.keywords[0]._astname; + if(astname === "keyword" && value.keywords[0].arg.v == "scl" + && value.keywords[0].value.func.attr.v === "Pin"){ + var sdablock = null; + var sclblock = null; + var freqblock = null; + var param = value.keywords[0]; + var key = py2block.identifier(param.arg); + var i2cblock=py2block.convert(targets[0]) + for (var i = 0; i < value.keywords.length; i++) { + var param = value.keywords[i]; + var key = py2block.identifier(param.arg); + if (key === "sda") { + pbc.inScope = "communicate_i2c_init"; + pbc.pinType = "pins_digital_pin"; + sdablock = py2block.convert(param.value.args[0]); + pbc.pinType = null; + pbc.inScope = null; + } else if (key === "scl") { + pbc.inScope = "communicate_i2c_init"; + pbc.pinType = "pins_digital_pin"; + sclblock = py2block.convert(param.value.args[0]); + pbc.pinType = null; + pbc.inScope = null; + } else if (key === "freq") { + freqblock = py2block.convert(param.value); + } + } +} + if (sdablock != null && sclblock != null && freqblock != null) { + return block("communicate_i2c_init", node.lineno, {}, { + "SUB":i2cblock, + 'RX': sdablock, + 'TX': sclblock, + "freq": freqblock + }, { + "inline": "true" + }); + } +} + +pbc.objectFunctionD.get('readfrom')['I2C'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var adblock = py2block.convert(args[0]); + var datablock = py2block.convert(args[1]); + return block("communicate_i2c_read", func.lineno, {}, { + "address": adblock, + "data": datablock, + "VAR": objblock + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('writeto')['I2C'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var adblock = py2block.convert(args[0]); + var datablock = py2block.convert(args[1]); + return [block("communicate_i2c_write", func.lineno, {}, { + "address": adblock, + "data": datablock, + "VAR": objblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('scan')['I2C'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("communicate_i2c_scan", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('read')[i2cClass] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("communicate_i2c_master_read", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('available')['I2C'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("communicate_i2c_available", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + }); +} + +pbc.assignD.get('SPI')['check_assign'] = function(py2block, node, targets, value) { + var funcName = py2block.identifier(value.func.attr); + var moduleName = py2block.Name_str(value.func.value); + if(value._astname === "Call" && moduleName === "machine" + && funcName === "SPI" && value.keywords.length === 6) + return true; + return false; +} + +pbc.assignD.get('SPI')['create_block'] = function(py2block, node, targets, value){ + + var astname = value.keywords[0]._astname; + if(value.keywords[0].arg.v == "baudrate" && value.keywords[3].arg.v == "sck" && value.keywords[3].value.func.attr.v == "Pin"){ + var polarityblock = null; + var phaseblock = null; + var sckblock = null; + var mosiblock = null; + var misoblock = null; + var freqblock = null; + var param = value.keywords[0]; + var key = py2block.identifier(param.arg); + var spiblock=py2block.convert(targets[0]); + for (var i = 0; i < value.keywords.length; i++) { + var param = value.keywords[i]; + var key = py2block.identifier(param.arg); + if (key === "baudrate") { + freqblock = py2block.convert(param.value); + } else if (key === "polarity") { + polarityblock = py2block.convert(param.value); + } else if (key === "phase") { + phaseblock = py2block.convert(param.value); + } else if (key === "sck") { + pbc.inScope = "communicate_spi_init"; + pbc.pinType = "pins_digital_pin"; + sckblock = py2block.convert(param.value.args[0]); + pbc.pinType = null; + pbc.inScope = null; + } else if (key === "mosi") { + pbc.inScope = "communicate_spi_init"; + pbc.pinType = "pins_digital_pin"; + mosiblock = py2block.convert(param.value.args[0]); + pbc.pinType = null; + pbc.inScope = null; + } else if (key === "miso") { + pbc.inScope = "communicate_spi_init"; + pbc.pinType = "pins_digital_pin"; + misoblock = py2block.convert(param.value.args[0]); + pbc.pinType = null; + pbc.inScope = null; + } + } +} + if (polarityblock != null && phaseblock != null && freqblock != null && sckblock != null && mosiblock != null && misoblock != null) { + return block("communicate_spi_init", node.lineno, {}, { + "VAR":spiblock, + "freq": freqblock, + "polarity": polarityblock, + "phase": phaseblock, + "sck": sckblock, + "mosi": mosiblock, + "miso": misoblock, + }, { + "inline": "true" + }); + } +} + +// 跟control的system_timer重了 +// pbc.objectFunctionD.get('init')['SPI'] = function (py2block, func, args, keywords, starargs, kwargs, node) { +// if (args.length == 0 & keywords.length == 1){ +// var objblock = py2block.convert(func.value); +// var btlblock = null; +// var param = keywords[0]; +// var key = py2block.identifier(param.arg); +// if (key === "baudrate") { +// bltblock = py2block.convert(param.value); +// } +// if (bltblock != null ) { +// return [block("communicate_spi_set", func.lineno, {}, { +// "VAR":objblock, +// "data": bltblock, +// }, { +// "inline": "true" +// })]; +// } +// }else{ +// throw new Error("Incorrect number of arguments"); +// } +// } + +pbc.assignD.get('spi')['check_assign'] = function(py2block, node, targets, value) { + if(value._astname != "Call" || value.func._astname != "Name"){ + return false; + } + var funcName = py2block.Name_str(value.func); + if(funcName === "bytearray" && value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('spi')['create_block'] = function(py2block, node, targets, value){ + return block("communicate_spi_buffer", node.lineno, { + }, { + "data":py2block.convert(value.args[0]), + "VAR":py2block.convert(targets[0]) + }); +} + +pbc.objectFunctionD.get('read')[spiClass] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1 & args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var byteblock = py2block.convert(args[0]); + if (args.length == 1){ + return block("communicate_spi_read", func.lineno, {}, { + "data": byteblock, + "VAR": objblock + }, { + "inline": "true" + }); + } + if (args.length == 2){ + var outputblock = py2block.convert(args[1]); + return block("communicate_spi_read_output", func.lineno, {}, { + "data": byteblock, + "val": outputblock, + "VAR": objblock + }, { + "inline": "true" + }); + } +} + +pbc.objectFunctionD.get('readinto')['SPI'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1 & args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var byteblock = py2block.convert(args[0]); + if (args.length == 1){ + return block("communicate_spi_readinto", func.lineno, {}, { + "data": byteblock, + "VAR": objblock + }, { + "inline": "true" + }); + } + if (args.length == 2){ + var outputblock = py2block.convert(args[1]); + return block("communicate_spi_readinto_output", func.lineno, {}, { + "data": byteblock, + "val": outputblock, + "VAR": objblock + }, { + "inline": "true" + }); + } +} + +pbc.objectFunctionD.get('write')[spiClass] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var byteblock = py2block.convert(args[0].func.value); + return block("communicate_spi_write", func.lineno, {}, { + "VAR": objblock, + "data": byteblock + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('write_readinto')['SPI'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var byteblock = py2block.convert(args[0].func.value); + var bufblock = py2block.convert(args[1]); + return block("communicate_spi_write_readinto", func.lineno, {}, { + "VAR": objblock, + "data": byteblock, + "val": bufblock + }, { + "inline": "true" + }); +} + +pbc.assignD.get('OW')['check_assign'] = function(py2block, node, targets, value) { + if(value._astname != "Call" || value.func._astname != "Attribute" || value.func.value._astname != "Name"){ + return false; + } + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" && moduleName === "onewire" + && funcName === "OneWire" && value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('OW')['create_block'] = function(py2block, node, targets, value){ + var pwmAstName = value.args[0]._astname; + pbc.pinType="pins_digital_pin"; + var pinblock; + + if (pwmAstName === "Call"&& value.args[0].func._astname == "Attribute" && value.args[0].func.attr.v==="Pin") { + pinblock=py2block.convert(value.args[0].args[0]) + } + pbc.pinType=null; + return block("communicate_ow_init", node.lineno, { + }, { + "BUS":pinblock, + "VAR":py2block.convert(targets[0]), + }); +} + +pbc.objectFunctionD.get('scan')[owClass] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("communicate_ow_scan", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('readbyte')['OW'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("communicate_ow_read", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('reset')['OW'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("communicate_ow_reset", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('select_rom')['OW'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var byteblock = py2block.convert(args[0].func.value); + return [block("communicate_ow_select", func.lineno, {}, { + "VAR": objblock, + "byte": byteblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('write')[owClass] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var byteblock = py2block.convert(args[0]); + return [block("communicate_ow_write", func.lineno, { + 'op':'write' + }, { + "VAR": objblock, + "byte": byteblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('writebyte')[owClass] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var byteblock = py2block.convert(args[0]); + return [block("communicate_ow_write", func.lineno, { + 'op':'writebyte' + }, { + "VAR": objblock, + "byte": byteblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('resume')['irremote'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + //var objblock = py2block.convert(func.value); + pbc.pinType = "pins_pwm_pin"; + var adblock = py2block.convert(args[0]); + pbc.pinType = "pins_callback"; + var datablock = py2block.convert(args[1]); + pbc.pinType=null; + return [block("communicate_ir_recv", func.lineno, {}, { + "PIN": adblock, + "SUB": datablock, + //"VAR": objblock + }, { + "inline": "true" + })]; +} diff --git a/mixly/boards/default_src/micropython/converters/control.js b/mixly/boards/default_src/micropython/converters/control.js new file mode 100644 index 00000000..ad6152a1 --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/control.js @@ -0,0 +1,139 @@ +'use strict'; + +pbc.moduleFunctionD.get('time')['sleep_ms'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + + var time=py2block.convert(args[0]); + return [block("controls_delay", func.lineno, {'Time':'ms'}, { + "DELAY_TIME":time + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('time')['sleep'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + + var time=py2block.convert(args[0]); + return [block("controls_delay", func.lineno, {'Time':'s'}, { + "DELAY_TIME":time + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('time')['sleep_us'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + + var time=py2block.convert(args[0]); + return [block("controls_delay", func.lineno, {'Time':'us'}, { + "DELAY_TIME":time + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('time')['ticks_ms'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + return block("controls_millis", func.lineno, {"Time":"ms"}, {}, { + "inline": "true" + }); +} +pbc.moduleFunctionD.get('time')['ticks_us'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + return block("controls_millis", func.lineno, {"Time":"us"}, {}, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('time')['ticks_diff'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var endblock=py2block.convert(args[0]); + var startblock=py2block.convert(args[1]); + return block("system_ticks_diff", func.lineno, {}, { + "END":endblock, + "START":startblock + }, { + "inline": "true" + }); +} + +pbc.assignD.get('Timer')['check_assign'] = function(py2block, node, targets, value) { + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" + && funcName === "Timer" && moduleName === "machine" && value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('Timer')['create_block'] = function(py2block, node, targets, value){ + + pbc.pinType = "variables_get"; + var timblock = py2block.convert(targets[0]); + pbc.pinType = null; + + + return block("system_timer_init", node.lineno, {}, { + "SUB":timblock, + + }); +} + +//跟通信的SPT init重了 +pbc.objectFunctionD.get('init')['control'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + + if(args.length === 0 && keywords.length ===3){ + pbc.pinType = "variables_get"; + var tim = py2block.convert(func.value); + pbc.pinType = null; + pbc.pinType = "math_number"; + var numblock = py2block.convert(keywords[0].value); + pbc.pinType = null; + var mode = py2block.identifier(keywords[1].value.attr); + pbc.pinType = "pins_callback"; + var callback = py2block.convert(keywords[2].value); + pbc.pinType = null; + + return [block("system_timer", func.lineno, {"mode":mode}, { + "VAR": tim, + "period":numblock, + "callback": callback + }, { + "inline": "true" + })]; +} + else if (args.length == 0 && keywords.length == 1){ + var objblock = py2block.convert(func.value); + var bltblock = null; + var param = keywords[0]; + var key = py2block.identifier(param.arg); + if (key === "baudrate") { + bltblock = py2block.convert(param.value); + } + if (bltblock != null ) { + return [block("communicate_spi_set", func.lineno, {}, { + "VAR":objblock, + "data": bltblock, + }, { + "inline": "true" + })]; + } + } + else{ + throw new Error("Incorrect number of arguments"); + } + +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/converters/display.js b/mixly/boards/default_src/micropython/converters/display.js new file mode 100644 index 00000000..2179094a --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/display.js @@ -0,0 +1,746 @@ +'use strict'; + +pbc.moduleFunctionD.get('matrix.display')['show'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1 && args.length !== 2 ){ + throw new Error("Incorrect number of arguments"); + } + if (args.length == 1 ){ + + var strblock=py2block.convert(args[0]); + + return [block("display_show_image_or_string", func.lineno, {}, { + 'data':strblock, + }, { + "inline": "true" + })]; + } + if (args.length == 2 ){ + var strblock=py2block.convert(args[0]); + var numblock=py2block.convert(args[1]); + return [block("display_show_image_or_string_delay", func.lineno, {}, { + 'data':strblock, + 'time':numblock + }, { + "inline": "true" + })]; + } +} + +pbc.moduleFunctionD.get('matrix.display')['scroll'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1 && args.length !== 2 ){ + throw new Error("Incorrect number of arguments"); + } + + if (args.length == 1 ){ + var strblock=py2block.convert(args[0]); + return [block("display_scroll_string", func.lineno, {}, { + 'data':strblock, + }, { + "inline": "true" + })]; + } + if (args.length == 2 ){ + var strblock=py2block.convert(args[0]); + var numblock=py2block.convert(args[1]); + return [block("display_scroll_string_delay", func.lineno, {}, { + 'data':strblock, + 'time':numblock + }, { + "inline": "true" + })]; + } +} + +pbc.moduleFunctionD.get('matrix.display')['showstatic'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1 && args.length !== 2 ){ + throw new Error("Incorrect number of arguments"); + } + + if (args.length == 1 ){ + var strblock=py2block.convert(args[0]); + return [block("display_show_static", func.lineno, {}, { + 'data':strblock, + }, { + "inline": "true" + })]; + } +} + +pbc.moduleFunctionD.get('matrix.display')['get_screenimage'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + + if (args.length == 0 ) { + return block("display_get_screen_image", func.lineno, {}, { + }, { + "inline": "true" + }); + } +} + +pbc.moduleFunctionD.get('matrix')['Image'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1 || args[0]._astname != "Str") { + throw new Error("Incorrect number of arguments"); + } + var colours = [ + "#000000", + "#ff0000", + ]; + var flag = 0; + var tempblock = py2block.Str_value(args[0]); + var temptext = new Array(); + temptext = tempblock.split(':'); + + if (temptext.length == 8) { + for (var i = 0; i < 8; i++) { + if (temptext[i].length == 16) { + flag++; + } + } + } + if (flag == 8) { + return block('display_image_create', func.lineno, { + "00": colours[temptext[0].charAt(0)], + "01": colours[temptext[0].charAt(1)], + "02": colours[temptext[0].charAt(2)], + "03": colours[temptext[0].charAt(3)], + "04": colours[temptext[0].charAt(4)], + "05": colours[temptext[0].charAt(5)], + "06": colours[temptext[0].charAt(6)], + "07": colours[temptext[0].charAt(7)], + "08": colours[temptext[0].charAt(8)], + "09": colours[temptext[0].charAt(9)], + "0a": colours[temptext[0].charAt(10)], + "0b": colours[temptext[0].charAt(11)], + "0c": colours[temptext[0].charAt(12)], + "0d": colours[temptext[0].charAt(13)], + "0e": colours[temptext[0].charAt(14)], + "0f": colours[temptext[0].charAt(15)], + + "10": colours[temptext[1].charAt(0)], + "11": colours[temptext[1].charAt(1)], + "12": colours[temptext[1].charAt(2)], + "13": colours[temptext[1].charAt(3)], + "14": colours[temptext[1].charAt(4)], + "15": colours[temptext[1].charAt(5)], + "16": colours[temptext[1].charAt(6)], + "17": colours[temptext[1].charAt(7)], + "18": colours[temptext[1].charAt(8)], + "19": colours[temptext[1].charAt(9)], + "1a": colours[temptext[1].charAt(10)], + "1b": colours[temptext[1].charAt(11)], + "1c": colours[temptext[1].charAt(12)], + "1d": colours[temptext[1].charAt(13)], + "1e": colours[temptext[1].charAt(14)], + "1f": colours[temptext[1].charAt(15)], + + "20": colours[temptext[2].charAt(0)], + "21": colours[temptext[2].charAt(1)], + "22": colours[temptext[2].charAt(2)], + "23": colours[temptext[2].charAt(3)], + "24": colours[temptext[2].charAt(4)], + "25": colours[temptext[2].charAt(5)], + "26": colours[temptext[2].charAt(6)], + "27": colours[temptext[2].charAt(7)], + "28": colours[temptext[2].charAt(8)], + "29": colours[temptext[2].charAt(9)], + "2a": colours[temptext[2].charAt(10)], + "2b": colours[temptext[2].charAt(11)], + "2c": colours[temptext[2].charAt(12)], + "2d": colours[temptext[2].charAt(13)], + "2e": colours[temptext[2].charAt(14)], + "2f": colours[temptext[2].charAt(15)], + + "30": colours[temptext[3].charAt(0)], + "31": colours[temptext[3].charAt(1)], + "32": colours[temptext[3].charAt(2)], + "33": colours[temptext[3].charAt(3)], + "34": colours[temptext[3].charAt(4)], + "35": colours[temptext[3].charAt(5)], + "36": colours[temptext[3].charAt(6)], + "37": colours[temptext[3].charAt(7)], + "38": colours[temptext[3].charAt(8)], + "39": colours[temptext[3].charAt(9)], + "3a": colours[temptext[3].charAt(10)], + "3b": colours[temptext[3].charAt(11)], + "3c": colours[temptext[3].charAt(12)], + "3d": colours[temptext[3].charAt(13)], + "3e": colours[temptext[3].charAt(14)], + "3f": colours[temptext[3].charAt(15)], + + "40": colours[temptext[4].charAt(0)], + "41": colours[temptext[4].charAt(1)], + "42": colours[temptext[4].charAt(2)], + "43": colours[temptext[4].charAt(3)], + "44": colours[temptext[4].charAt(4)], + "45": colours[temptext[4].charAt(5)], + "46": colours[temptext[4].charAt(6)], + "47": colours[temptext[4].charAt(7)], + "48": colours[temptext[4].charAt(8)], + "49": colours[temptext[4].charAt(9)], + "4a": colours[temptext[4].charAt(10)], + "4b": colours[temptext[4].charAt(11)], + "4c": colours[temptext[4].charAt(12)], + "4d": colours[temptext[4].charAt(13)], + "4e": colours[temptext[4].charAt(14)], + "4f": colours[temptext[4].charAt(15)], + + + "50": colours[temptext[5].charAt(0)], + "51": colours[temptext[5].charAt(1)], + "52": colours[temptext[5].charAt(2)], + "53": colours[temptext[5].charAt(3)], + "54": colours[temptext[5].charAt(4)], + "55": colours[temptext[5].charAt(5)], + "56": colours[temptext[5].charAt(6)], + "57": colours[temptext[5].charAt(7)], + "58": colours[temptext[5].charAt(8)], + "59": colours[temptext[5].charAt(9)], + "5a": colours[temptext[5].charAt(10)], + "5b": colours[temptext[5].charAt(11)], + "5c": colours[temptext[5].charAt(12)], + "5d": colours[temptext[5].charAt(13)], + "5e": colours[temptext[5].charAt(14)], + "5f": colours[temptext[5].charAt(15)], + + "60": colours[temptext[6].charAt(0)], + "61": colours[temptext[6].charAt(1)], + "62": colours[temptext[6].charAt(2)], + "63": colours[temptext[6].charAt(3)], + "64": colours[temptext[6].charAt(4)], + "65": colours[temptext[6].charAt(5)], + "66": colours[temptext[6].charAt(6)], + "67": colours[temptext[6].charAt(7)], + "68": colours[temptext[6].charAt(8)], + "69": colours[temptext[6].charAt(9)], + "6a": colours[temptext[6].charAt(10)], + "6b": colours[temptext[6].charAt(11)], + "6c": colours[temptext[6].charAt(12)], + "6d": colours[temptext[6].charAt(13)], + "6e": colours[temptext[6].charAt(14)], + "6f": colours[temptext[6].charAt(15)], + + + "70": colours[temptext[7].charAt(0)], + "71": colours[temptext[7].charAt(1)], + "72": colours[temptext[7].charAt(2)], + "73": colours[temptext[7].charAt(3)], + "74": colours[temptext[7].charAt(4)], + "75": colours[temptext[7].charAt(5)], + "76": colours[temptext[7].charAt(6)], + "77": colours[temptext[7].charAt(7)], + "78": colours[temptext[7].charAt(8)], + "79": colours[temptext[7].charAt(9)], + "7a": colours[temptext[7].charAt(10)], + "7b": colours[temptext[7].charAt(11)], + "7c": colours[temptext[7].charAt(12)], + "7d": colours[temptext[7].charAt(13)], + "7e": colours[temptext[7].charAt(14)], + "7f": colours[temptext[7].charAt(15)], + + }, {}, { + "inline": "false" + }); + } +} +function shift(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=1){ + throw new Error("Incorrect number of arguments"); + } + var str1block=py2block.convert(args[0]); + var imgblock=py2block.convert(func.value); + return block("image_shift", func.lineno, { + 'OP':mode + }, { + 'img':imgblock, + 'val':str1block + }, { + "inline": "true" + }); + } + return converter; +} +pbc.objectFunctionD.get('shift_up')['matrix'] = shift('up'); +pbc.objectFunctionD.get('shift_down')['matrix'] = shift('down'); +pbc.objectFunctionD.get('shift_left')['matrix'] = shift('left'); +pbc.objectFunctionD.get('shift_right')['matrix'] = shift('right'); + +pbc.moduleFunctionD.get('matrix.display')['get_pixel'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 2){ + throw new Error("Incorrect number of arguments"); + } + var astname = args[0]._astname; + var astname1 = args[1]._astname; + var xblock; + var yblock; + pbc.pinType = "pins_axis"; + if(astname === "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) === "int"){ //display.get_pixel(int(0), int(0)) + xblock = py2block.convert(args[0].args[0]); + }else{ + xblock = py2block.convert(args[0]); + } + if(astname1 === "Call" && args[1].func._astname == "Name" && py2block.Name_str(args[1].func) === "int"){ //display.get_pixel(int(0), int(0)) + yblock = py2block.convert(args[1].args[0]); + }else{ + yblock = py2block.convert(args[1]); + } + pbc.pinType = null; + return block("display_get_pixel", func.lineno, {}, { + 'x':xblock, + 'y':yblock + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('matrix.display')['set_pixel'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 3){ + throw new Error("Incorrect number of arguments"); + } + var astname = args[0]._astname; + var astname1 = args[1]._astname; + pbc.pinType = null; + pbc.inScope="switch"; + var brightblock = py2block.convert(args[2]); + pbc.inScope=null; + pbc.pinType = null; + var xblock; + var yblock; + pbc.pinType = "pins_axis"; + if(astname === "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) === "int"){ //display.set_pixel(int(0), int(0)) + xblock = py2block.convert(args[0].args[0]); + }else{ + xblock = py2block.convert(args[0]); + } + if(astname1 === "Call" && args[1].func._astname == "Name" && py2block.Name_str(args[1].func) === "int"){ //display.set_pixel(int(0), int(0)) + yblock = py2block.convert(args[1].args[0]); + }else{ + yblock = py2block.convert(args[1]); + } + pbc.pinType = null; + return [block("display_bright_point", func.lineno, {}, { + 'x':xblock, + 'y':yblock, + 'STAT':brightblock + + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('matrix.display')['set_brightness'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=1){ + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="pins_exlcdh"; + var brightblock=py2block.convert(args[0]); + pbc.pinType=null; + + return [block("display_bright_screen", func.lineno, {}, { + 'x':brightblock, + + + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('matrix.display')['get_brightness'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=0){ + throw new Error("Incorrect number of arguments"); + } + + return block("display_get_screen_pixel", func.lineno, {}, { + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('matrix.display')['blink_rate'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=1){ + throw new Error("Incorrect number of arguments"); + } + var blinkblock=py2block.convert(args[0]); + + return [block("display_blink_rate", func.lineno, {}, { 'x':blinkblock, + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('matrix.display')['clear'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=0){ + throw new Error("Incorrect number of arguments"); + } + + + return [block("display_clear", func.lineno, {}, { + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_pixel')['monitor'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=2){ + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var x1block=py2block.convert(args[0]); + var y1block=py2block.convert(args[1]); + + return [block("display_oled_drawPixel", func.lineno, {}, { "VAR":objblock,'POS_X':x1block,'POS_Y':y1block, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_bitmap')['monitor'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=5){ + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var x=py2block.convert(args[0]); + var y=py2block.convert(args[1]); + var b=py2block.convert(args[2]); + var w=py2block.convert(args[3]); + var h=py2block.convert(args[4]); + return [block("display_oled_showBitmap", func.lineno, {}, { "VAR":objblock,'START_X':x,'START_Y':y,'bitmap_name':b,'WIDTH':w,'HEIGHT':h, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_str')['monitor'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=4){ + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var str1block=py2block.convert(args[0]); + var str2block=py2block.convert(args[1]); + var str3block=py2block.convert(args[2]); + var str4block=py2block.convert(args[3]); + + return [block("display_draw_4strings", func.lineno, {}, { "VAR":objblock,'Text_line1':str1block,'Text_line2':str2block,'Text_line3':str3block,'Text_line4':str4block, + }, { + "inline": "false" + })]; +} + +pbc.objectFunctionD.get('show_line')['monitor'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=5){ + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var x1block=py2block.convert(args[0]); + var y1block=py2block.convert(args[1]); + var x2block=py2block.convert(args[2]); + var y2block=py2block.convert(args[3]); + + return [block("display_line_arbitrarily", func.lineno, {}, { "VAR":objblock,'x1':x1block,'y1':y1block,'x2':x2block,'y2':y2block, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_hline')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 4) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var xblock = py2block.convert(args[0]); + var yblock = py2block.convert(args[1]); + var lenblock = py2block.convert(args[2]); + return [block("display_line", func.lineno, { + 'direction': 'hline', + }, { + "VAR":objblock, + "x": xblock, + "y": yblock, + "length": lenblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_vline')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 4) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var xblock = py2block.convert(args[0]); + var yblock = py2block.convert(args[1]); + var lenblock = py2block.convert(args[2]); + return [block("display_line", func.lineno, { + 'direction': 'vline', + }, { + "VAR":objblock, + "x": xblock, + "y": yblock, + "length": lenblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_rect')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 5) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var xblock = py2block.convert(args[0]); + var yblock = py2block.convert(args[1]); + var widthblock = py2block.convert(args[2]); + var heightblock = py2block.convert(args[3]); + var lightblock = py2block.identifier(args[4].n); + return [block("display_rect", func.lineno, { + "fill": false, + "OP": lightblock, + }, { + "VAR":objblock, + "x": xblock, + "y": yblock, + "width": widthblock, + "height": heightblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_fill_rect')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 5) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var xblock = py2block.convert(args[0]); + var yblock = py2block.convert(args[1]); + var widthblock = py2block.convert(args[2]); + var heightblock = py2block.convert(args[3]); + var lightblock = py2block.identifier(args[4].n); + return [block("display_rect", func.lineno, { + "fill": true, + "OP": lightblock, + }, { + "VAR":objblock, + "x": xblock, + "y": yblock, + "width": widthblock, + "height": heightblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_triangle')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 7) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var x0 = py2block.convert(args[0]); + var y0 = py2block.convert(args[1]); + var x1 = py2block.convert(args[2]); + var y1 = py2block.convert(args[3]); + var x2 = py2block.convert(args[4]); + var y2 = py2block.convert(args[5]); + var lightblock = py2block.identifier(args[6].n); + return [block("display_triangle", func.lineno, { + "fill": false, + "OP": lightblock, + }, { + "VAR":objblock, + "x0": x0, + "y0": y0, + "x1": x1, + "y1": y1, + "x2": x2, + "y2": y2, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_fill_triangle')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 7) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var x0 = py2block.convert(args[0]); + var y0 = py2block.convert(args[1]); + var x1 = py2block.convert(args[2]); + var y1 = py2block.convert(args[3]); + var x2 = py2block.convert(args[4]); + var y2 = py2block.convert(args[5]); + var lightblock = py2block.identifier(args[6].n); + return [block("display_triangle", func.lineno, { + "fill": true, + "OP": lightblock, + }, { + "VAR":objblock, + "x0": x0, + "y0": y0, + "x1": x1, + "y1": y1, + "x2": x2, + "y2": y2, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_circle')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 4) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var xblock = py2block.convert(args[0]); + var yblock = py2block.convert(args[1]); + var rblock = py2block.convert(args[2]); + var lightblock = py2block.identifier(args[3].n); + return [block("display_circle", func.lineno, { + "fill": false, + "OP": lightblock, + }, { + "VAR":objblock, + "x": xblock, + "y": yblock, + "r": rblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('show_fill_circle')['monitor'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 4) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var xblock = py2block.convert(args[0]); + var yblock = py2block.convert(args[1]); + var rblock = py2block.convert(args[2]); + var lightblock = py2block.identifier(args[3].n); + return [block("display_circle", func.lineno, { + "fill": true, + "OP": lightblock, + }, { + "VAR":objblock, + "x": xblock, + "y": yblock, + "r": rblock, + }, { + "inline": "true" + })]; +} + + +pbc.assignD.get('oled')['check_assign'] = function(py2block, node, targets, value) { + if(value._astname != "Call" || value.func._astname != "Attribute" || value.func.value._astname != "Name"){ + return false; + } + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" && moduleName === "ssd1306" + && funcName === "SSD1306_I2C" && value.args.length === 3) + return true; + else if(value._astname === "Call" && moduleName === "tm1650" + && funcName === "TM1650" && value.args.length === 1) + return true; + else + return false; +} + +pbc.assignD.get('oled')['create_block'] = function(py2block, node, targets, value){ + if(value.args.length === 3){ + var rowblock = py2block.convert(value.args[0]); + var columnblock = py2block.convert(value.args[1]); + var i2cblock = py2block.convert(value.args[2]); + return block("display_use_i2c_init", node.lineno, { + }, { + "row":rowblock, + "column":columnblock, + "I2CSUB":i2cblock, + "SUB":py2block.convert(targets[0]), + }); + } + else if(value.args.length === 1){ + var i2cblock = py2block.convert(value.args[0]); + return block("display_tm_use_i2c_init", node.lineno, { + }, { + "I2CSUB":i2cblock, + "SUB":py2block.convert(targets[0]), + }); + } +} + +pbc.objectFunctionD.get('show_fill')['monitor'] = function(py2block, func, args, keywords, starargs, kwargs, node) { + if(args.length!=1){ + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var flagblock = py2block.identifier(args[0].n.v); + + + return [block("display_fill", func.lineno, {'key':flagblock}, { "SUB":objblock, + }, { + "inline": "true" + })]; +} + +function display_tm_stat(mode, type){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var varblock = py2block.convert(func.value) + return [block('display_tm1650_power', func.lineno, { + "TYPE": type, + "STAT": mode, + }, { + "VAR": varblock, + }, { + "inline": "true" + })]; + } + return converter; +} + +pbc.objectFunctionD.get('tm1650_on')['disp'] = display_tm_stat('_on','tm1650'); +pbc.objectFunctionD.get('tm1650_off')['disp'] = display_tm_stat('_off','tm1650'); +pbc.objectFunctionD.get('tm1650_clear')['disp'] = display_tm_stat('_clear','tm1650'); + + +pbc.objectFunctionD.get('tm1650_show_num')['disp'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var valblock=py2block.convert(args[0]); + var varblock=py2block.convert(func.value) + return [block("display_tm1650_show_num", func.lineno, { + "TYPE":'tm1650' + }, { + 'VALUE':valblock, + 'VAR': varblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('tm1650_show_dot')['disp'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var valblock=py2block.convert(args[0]); + pbc.inScope="switch"; + var statblock=py2block.convert(args[1]); + pbc.inScope=null; + var varblock=py2block.convert(func.value) + return [block("display_tm1650_show_dot", func.lineno, { + "TYPE":'tm1650' + }, { + 'NO':valblock, + 'STAT':statblock, + 'VAR': varblock + }, { + "inline": "true" + })]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/converters/inout.js b/mixly/boards/default_src/micropython/converters/inout.js new file mode 100644 index 00000000..a8c1c1af --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/inout.js @@ -0,0 +1,295 @@ + + +pbc.objectFunctionD.get('value')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1 && args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + if(args.length == 1){ + pbc.pinType = "pins_digital"; + var pinblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + pbc.pinType = null; + return [block("inout_digital_write", func.lineno, {}, { + "PIN": pinblock, + "STAT": argblock + }, { + "inline": "true" + })];} + else if(args.length == 0){ + pbc.pinType = "pins_digital"; + var pinblock = py2block.convert(func.value); + pbc.pinType = null; + return block("inout_digital_read", func.lineno, {}, { + "PIN": pinblock + }, { + "inline": "true" + }); + } +} + + +pbc.assignD.get('Pin')['check_assign'] = function(py2block, node, targets, value) { + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" + && funcName === "Pin" && (value.args.length === 2 || value.args.length === 3) ) + return true; + return false; +} + +pbc.assignD.get('Pin')['create_block'] = function(py2block, node, targets, value){ + + pbc.pinType = "pins_digital_pin"; + var pinblock = py2block.convert(value.args[0]); + pbc.pinType = null; + if(value.args.length === 2){ + var digitalblock = "machine."+py2block.identifier(value.args[1].value.attr) +"."+ py2block.identifier(value.args[1].attr); + } + else if(value.args.length === 3){ + var digitalblock = "machine."+py2block.identifier(value.args[1].value.attr) +"."+ py2block.identifier(value.args[1].attr)+", "+"machine."+py2block.identifier(value.args[2].value.attr) +"."+ py2block.identifier(value.args[2].attr); + } + pinobj = py2block.identifier(targets[0].id); + return block("inout_digital_init", node.lineno, {"PIN_OBJ":pinobj,"MODE":digitalblock}, { + "PIN":pinblock, + + }); +} +//ok +pbc.assignD.get('DAC')['check_assign'] = function(py2block, node, targets, value) { + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" + && funcName === "DAC" && moduleName === "machine"&& value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('DAC')['create_block'] = function(py2block, node, targets, value){ + var astname = value.args[0]._astname; + var funcName = py2block.identifier(value.args[0].func.attr); + if(astname === "Call" && funcName === "Pin"){ // + pbc.pinType = "pins_dac_pin"; + pinblock = py2block.convert(value.args[0].args[0]); + pbc.pinType = null; + }else{ + pbc.pinType = "pins_dac_pin"; + pinblock = py2block.convert(args[0]); + pbc.pinType = null; + } + pinobj = py2block.identifier(targets[0].id); + return block("inout_analog_write_init", node.lineno, {"PIN_OBJ":pinobj}, { + "PIN":pinblock, + + }); +} + +pbc.objectFunctionD.get('write')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType = "pins_dac"; + var pinblock = py2block.convert(func.value); + pbc.pinType = null; + var argblock = py2block.convert(args[0]); + + return [block("inout_analog_write", func.lineno, {}, { + "PIN": pinblock, + "NUM": argblock + }, { + "inline": "true" + })]; +} + +//ok +pbc.assignD.get('PWM')['check_assign'] = function(py2block, node, targets, value) { + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" + && funcName === "PWM" && moduleName === "machine" && value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('PWM')['create_block'] = function(py2block, node, targets, value){ + var astname = value.args[0]._astname; + var funcName = py2block.identifier(value.args[0].func.attr); + if(astname === "Call" && funcName === "Pin"){ // + pbc.pinType = "pins_pwm_pin"; + pinblock = py2block.convert(value.args[0].args[0]); + pbc.pinType = null; + }else{ + pbc.pinType = "pins_pwm_pin"; + pinblock = py2block.convert(args[0]); + pbc.pinType = null; + } + pinobj = py2block.identifier(targets[0].id); + return block("inout_pwm_analog_write_init", node.lineno, {"PIN_OBJ":pinobj}, { + "PIN":pinblock, + + }); +} + +pbc.objectFunctionD.get('duty')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType = "pins_pwm"; + var pinblock = py2block.convert(func.value); + pbc.pinType = null; + var argblock = py2block.convert(args[0]); + + return [block("inout_pwm_analog_write", func.lineno, {}, { + "PIN": pinblock, + "NUM": argblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('freq')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType = "pins_pwm"; + var pinblock = py2block.convert(func.value); + pbc.pinType = null; + var argblock = py2block.convert(args[0]); + + return [block("inout_pwm_analog_write_set_freq", func.lineno, {}, { + "PIN": pinblock, + "NUM": argblock + }, { + "inline": "true" + })]; +} +//ok +pbc.assignD.get('ADC')['check_assign'] = function(py2block, node, targets, value) { + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" + && funcName === "ADC" && moduleName === "machine" && value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('ADC')['create_block'] = function(py2block, node, targets, value){ + var astname = value.args[0]._astname; + var funcName = py2block.identifier(value.args[0].func.attr); + if(astname === "Call" && funcName === "Pin"){ // + pbc.pinType = "pins_analog_pin"; + pinblock = py2block.convert(value.args[0].args[0]); + pbc.pinType = null; + }else{ + pbc.pinType = "pins_analog_pin"; + pinblock = py2block.convert(args[0]); + pbc.pinType = null; + } + pinobj = py2block.identifier(targets[0].id); + return block("inout_analog_read_init", node.lineno, {"PIN_OBJ":pinobj}, { + "PIN":pinblock, + + }); +} + +pbc.objectFunctionD.get('read')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + value = func.value.id.v + value = value.slice(0,2) + if( value=="ad"){ + pbc.pinType = "pins_analog"; + var pinblock = py2block.convert(func.value); + pbc.pinType = null; + + return block("inout_analog_read", func.lineno, {}, { + "PIN": pinblock, + }, { + "inline": "true" + });} + else if(value =="tc"){ + pbc.pinType = "pins_touch"; + var pinblock = py2block.convert(func.value); + pbc.pinType = null; + + return block("inout_pin_pressed", func.lineno, {}, { + "pin": pinblock, + }, { + "inline": "true" + }); + } +} +//ok +pbc.assignD.get('TOUCHPAD')['check_assign'] = function(py2block, node, targets, value) { + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" + && funcName === "TouchPad" && moduleName === "machine" && value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('TOUCHPAD')['create_block'] = function(py2block, node, targets, value){ + var astname = value.args[0]._astname; + var funcName = py2block.identifier(value.args[0].func.attr); + if(astname === "Call" && funcName === "Pin"){ // + pbc.pinType = "pins_touch_pin"; + pinblock = py2block.convert(value.args[0].args[0]); + pbc.pinType = null; + }else{ + pbc.pinType = "pins_touch_pin"; + pinblock = py2block.convert(args[0]); + pbc.pinType = null; + } + pinobj = py2block.identifier(targets[0].id); + return block("inout_pin_pressed_init", node.lineno, {"PIN_OBJ":pinobj}, { + "PIN":pinblock, + + }); +} + +pbc.objectFunctionD.get('irq')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0 || keywords.length!==2) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="Pin" && mac==="machine"){ + + pbc.pinType = "pins_digital_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + + var mode = mac+"."+pin+"."+py2block.identifier(keywords[1].value.attr); + + pbc.pinType = "pins_callback"; + var callback = py2block.convert(keywords[0].value); + pbc.pinType = null; + + return [block("inout_pin_attachInterrupt", func.lineno, {"mode":mode}, { + "PIN": pinblock, + "DO": callback + }, { + "inline": "true" + })]; +} + +} + +pbc.objectFunctionD.get('atten')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + + pbc.pinType = "pins_analog"; + var pinblock = py2block.convert(func.value); + pbc.pinType = null; + + var atten = py2block.identifier(args[0].value.value.id)+"."+py2block.identifier(args[0].value.attr)+"."+py2block.identifier(args[0].attr) + + return [block("inout_analog_atten", func.lineno, {"atten":atten}, { + "PIN": pinblock, + }, { + "inline": "true" + })]; +} diff --git a/mixly/boards/default_src/micropython/converters/iot.js b/mixly/boards/default_src/micropython/converters/iot.js new file mode 100644 index 00000000..7639f50d --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/iot.js @@ -0,0 +1,113 @@ +'use strict'; +// console.log("hhh") + +pbc.assignD.get('iot')['check_assign'] = function(py2block, node, targets, value) { + if(value._astname != "Call" || value.func._astname != "Attribute" || value.func.value._astname != "Name"){ + return false; + } + var funcName = py2block.identifier(value.func.attr); + var moduleName = py2block.Name_str(value.func.value); + if(moduleName === "miot" && funcName === "init_MQTT_client" && value.args.length === 6) + return true; + return false; +} + +pbc.assignD.get('iot')['create_block'] = function(py2block, node, targets, value){ + pbc.pinType = "pins_callback"; + var subblock = py2block.convert(value.args[5]); + pbc.pinType = null; + return block("iot_onenet_connect", node.lineno, {}, { + "CLIENT":py2block.convert(value.args[0]), + "SERVER":py2block.convert(value.args[1]), + "USERNAME":py2block.convert(value.args[2]), + "PASSWORD":py2block.convert(value.args[3]), + "TOPIC":py2block.convert(value.args[4]), + "SUB":subblock, + "VAR":py2block.convert(targets[0]) + }); +} + +// pbc.globalFunctionD['do_connect'] = function(py2block, func, args, keywords, starargs, kwargs, node){ +// if (args.length !== 2) { +// throw new Error("Incorrect number of arguments"); +// } +// var nameblock = py2block.convert(args[0]); +// var keyblock = py2block.convert(args[1]); +// return [block("iot_wifi_connect", func.lineno, {}, { +// 'WIFINAME': nameblock, +// 'PASSWORD': keyblock +// }, { +// "inline": "true" +// })]; +// } + +pbc.objectFunctionD.get('do_connect')['miot'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 2) { + throw new Error("Incorrect number of arguments"); + } + var nameblock = py2block.convert(args[0]); + var keyblock = py2block.convert(args[1]); + return [block("iot_wifi_connect", func.lineno, {}, { + 'WIFINAME': nameblock, + 'PASSWORD': keyblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('publish')['miot'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length == 1 && keywords.length == 1) { + var objblock = py2block.convert(func.value); + var nameblock = py2block.convert(args[0]); + var checkblock = py2block.Name_str(keywords[0].value); + return [block("iot_onenet_publish_dict", func.lineno, { + "is_print":checkblock + }, { + "VAR":objblock, + "DICT":nameblock + }, { + "inline": "true" + })]; + } + else if(args.length == 2) { + var objblock = py2block.convert(func.value); + var nameblock = py2block.convert(args[0]); + var checkblock = py2block.Name_str(args[1]); + return [block("iot_onenet_publish_dict", func.lineno, { + "is_print":checkblock + }, { + "VAR":objblock, + "DICT":nameblock + }, { + "inline": "true" + })]; + } + else + throw new Error("Incorrect number of arguments"); +} + +pbc.objectFunctionD.get('do_disconnect')['miot'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("iot_onenet_disconnect", func.lineno, {}, { + "VAR":objblock, + }, { + "inline": "true" + })]; +} + + +pbc.objectFunctionD.get('check_msg')['iot'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("iot_onenet_check", func.lineno, {}, { + "VAR":objblock, + }, { + "inline": "true" + })]; +} + diff --git a/mixly/boards/default_src/micropython/converters/network.js b/mixly/boards/default_src/micropython/converters/network.js new file mode 100644 index 00000000..c56cf946 --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/network.js @@ -0,0 +1,308 @@ +'use strict'; +// console.log("hhh") + +pbc.assignD.get('network')['check_assign'] = function(py2block, node, targets, value) { + if(value._astname != "Call" || value.func._astname != "Attribute" || value.func.value._astname != "Name"){ + return false; + } + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" && moduleName === "network" + && funcName === "WLAN" && value.args.length === 1) + return true; + return false; +} + +pbc.assignD.get('network')['create_block'] = function(py2block, node, targets, value){ + var mode = py2block.identifier(value.args[0].attr); + if (mode=="STA_IF"){ + mode="STA" + } + else if (mode=="AP_IF"){ + mode="AP" + } + return block("network_init", node.lineno, { + "mode":mode, + }, { + "VAR":py2block.convert(targets[0]), + }); +} + + +pbc.objectFunctionD.get('active')['network'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + + if (args.length === 1){ + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + var reverse = py2block.Name_str(args[0]); + return [block("network_open", func.lineno, { + "op": reverse, + }, { + "VAR":objblock, + }, { + "inline": "true" + })]; + } + else if (args.length === 0) { + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + return [block("network_is_active", func.lineno, { + }, { + "VAR":objblock, + }, { + "inline": "true" + })]; + } + else + { + throw new Error("Incorrect number of arguments"); + } + + +} + +pbc.objectFunctionD.get('isconnected')['network'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("network_wifi_connect", func.lineno, {}, { + "VAR":objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('disconnect')['network'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("network_stop", func.lineno, {}, { + "VAR":objblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('config')['network'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length == 0 & keywords.length == 2){ + var objblock = py2block.convert(func.value); + var essidblock = null; + var channelblock = null; + for (var i = 0; i < keywords.length; i++) { + var param = keywords[i]; + var key = py2block.identifier(param.arg); + if (key === "essid") { + essidblock = py2block.convert(param.value); + } else if (key === "channel") { + channelblock = py2block.convert(param.value); + } + } + if (essidblock != null && channelblock != null ) { + return [block("network_ap_connect", func.lineno, {}, { + "VAR":objblock, + "essid": essidblock, + "channel": channelblock, + }, { + "inline": "true" + })]; + } + }else if(args.length == 1) { + var objblock = py2block.convert(func.value); + var argblock = py2block.Str_value(args[0]); + return block("network_get_wifi", func.lineno, { + "op":argblock, + }, { + "VAR":objblock, + }, { + "inline": "true" + }); + }else{ + throw new Error("Incorrect number of arguments"); + } +} + +pbc.objectFunctionD.get('connect')['network'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length === 2) { + var objblock = py2block.convert(func.value); + var idblock = py2block.convert(args[0]); + var passwordblock = py2block.convert(args[1]); + return [block("network_connect", func.lineno, {}, { + "VAR":objblock, + "id":idblock, + "password":passwordblock, + }, { + "inline": "true" + })]; + } + else if (args.length === 1) { + var objblock = py2block.convert(func.value); + var reverse = py2block.convert(args[0]); + return [block("network_socket_connect", func.lineno, { + }, { + "address": reverse, + "VAR":objblock, + }, { + "inline": "true" + })]; + } + else { + throw new Error("Incorrect number of arguments"); + } +} + +pbc.assignD.get('socket')['check_assign'] = function(py2block, node, targets, value) { + if(value._astname != "Call" || value.func._astname != "Attribute" || value.func.value._astname != "Name"){ + return false; + } + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" && moduleName === "socket" + && funcName === "socket" && value.args.length <= 1) + return true; + return false; +} + +pbc.assignD.get('socket')['create_block'] = function(py2block, node, targets, value){ + value.args = value.args || []; + if (!value.args.length){ + var mode="TCP" + } + else { + var mode = py2block.identifier(value.args[0].attr); + if (mode == "SOCK_DGRAM"){ + mode = "UDP" + } + else if (mode == "SOCK_STREAM"){ + mode = "TCP" + } + } + return block("network_socket_init", node.lineno, { + "mode":mode, + }, { + "VAR":py2block.convert(targets[0]), + }); +} + +pbc.objectFunctionD.get('bind')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + var reverse = py2block.convert(args[0]); + return [block("network_socket_bind", func.lineno, { + }, { + "address": reverse, + "VAR":objblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('listen')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + var reverse = py2block.convert(args[0]); + return [block("network_socket_listen", func.lineno, { + }, { + "queue": reverse, + "VAR":objblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('accept')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("network_socket_accept", func.lineno, {}, { + "VAR":objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('recv')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + var reverse = py2block.convert(args[0]); + return block("network_socket_receive", func.lineno, { + }, { + "size": reverse, + "VAR":objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('send')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + var reverse = py2block.convert(args[0]); + return [block("network_socket_send", func.lineno, { + }, { + "content": reverse, + "VAR":objblock, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('recvfrom')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + var reverse = py2block.convert(args[0]); + return block("network_socket_receive_from", func.lineno, { + }, { + "size": reverse, + "VAR":objblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('sendto')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + // var lightblock = py2block.identifier(args[0].n); + var reverse = py2block.convert(args[0]); + var address = py2block.convert(args[1]); + return [block("network_socket_send_to", func.lineno, { + }, { + "content": reverse, + "VAR":objblock, + "address":address, + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('close')['socket'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("network_socket_close", func.lineno, {}, { + "VAR":objblock, + }, { + "inline": "true" + })]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/converters/py2block_config.js b/mixly/boards/default_src/micropython/converters/py2block_config.js new file mode 100644 index 00000000..eb3031b1 --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/py2block_config.js @@ -0,0 +1,113 @@ +function defDict(type) { + var dict = {}; + return { + get: function (key) { + if (!dict[key]) { + dict[key] = type.constructor(); + } + return dict[key]; + }, + dict: dict + }; +} + +function Py2blockConfig (){ + this.initIgnoreS(); + this.initModuleAttrD(); + this.initKnownModuleS(); + this.initObjectTypeD(); + this.formatModuleKeyL = [ + ['Pin', 'ADC', 'TouchPad', 'PWM', 'DAC', 'I2C'], + ['button_a', 'button_b', 'touch1', 'touch2', 'touch3', 'touch4', 'Infrared_left', 'Infrared_right', + 'mixgo_get_brightness', 'mixgo_get_soundlevel', 'Sonar', 'led', 'led1','led2','Infrared'], + ['NeoPixel'], + ['display', 'Image'] + ]; + this.formatModuleL = ['machine', 'mixgo', 'neopixel', 'matrix']; +} + +var pbc = Py2blockConfig.prototype; +pbc.ESP32 = "MicroPython[ESP32]"; +pbc.board = pbc.ESP32; +pbc.objectFunctionD = defDict({}); +pbc.moduleFunctionD = defDict({}); +pbc.moduleAttrD = defDict({}); +pbc.objectAttrD = defDict({}); +pbc.globalFunctionD = {}; +pbc.assignD = defDict({}); +pbc.ifStatementD= defDict({}); +pbc.whileStatementD= defDict({}); +pbc.forStatementD= defDict({}); +pbc.reservedNameD= {}; +pbc.knownModuleS = new Set(); +pbc.objectTypeD = {}; //key:变量名,value:变量类型,如{'a':'List'} +pbc.ignoreS = new Set(); +pbc.pinType = null; +pbc.inScope = null; +pbc.formatModuleKeyL = []; +pbc.formatModuleL = []; + +//忽略某些方法、类、赋值 +pbc.initIgnoreS = function(){ + var pythonIgnoreL = [ + ]; + var boardIgnoreL = [ + ]; + + var ignoreL = pythonIgnoreL.concat(boardIgnoreL); + for (var i = 0; i < ignoreL.length; i++) { + this.ignoreS.add(ignoreL[i]); + } +} + +pbc.initModuleAttrD = function(){ + for (var i = 0; i < profile.default.builtinimg.length; i++) { + pbc.moduleAttrD.get('matrix.Image')[profile.default.builtinimg[i][0]] = function (node, module, attr) { + return block("pins_builtinimg", node.lineno, { + "PIN": module + "." + attr + }); + } + } + for (var i = 0; i < profile.default.imglist.length; i++) { + pbc.moduleAttrD.get('Image')[profile.default.imglist[i][0]] = function (node, module, attr) { + return block("pins_imglist", node.lineno, { + "PIN": module + "." + attr + }); + } + } + for (var i = 0; i < profile.default.playlist.length; i++) { + pbc.moduleAttrD.get('music')[profile.default.playlist[i][0]] = function (node, module, attr) { + return block("pins_playlist", node.lineno, { + "PIN": module + "." + attr + }); + } + } +} + +pbc.initKnownModuleS = function(){ + var pythonModuleL = [ + 'math', 'random' + ]; + var boardModuleL = []; + + var moduleL = pythonModuleL.concat(boardModuleL); + for (var i = 0; i < moduleL.length; i++) { + this.knownModuleS.add(moduleL[i]); + } +} + +pbc.initObjectTypeD = function () { + this.objectTypeD = { + 'f': 'open', + 'spi': 'machine.SPI', + 'i2c': 'machine.I2C', + 'ow': 'onewire.OneWire', + } +} + +pbc.reset = function(){ + this.initObjectTypeD(); +} + +var py2block_config = new Py2blockConfig(); + diff --git a/mixly/boards/default_src/micropython/converters/sensor.js b/mixly/boards/default_src/micropython/converters/sensor.js new file mode 100644 index 00000000..799531d6 --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/sensor.js @@ -0,0 +1,734 @@ +'use strict'; + +function pressed_converter (mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pinType = "pins_button"; + var objblock = py2block.convert(btn); + pbc.pinType = null; + return block(mode, func.lineno, {}, { + "btn": objblock + }, { + "inline": "true" + }); + } + return converter; +} + + +pbc.moduleFunctionD.get('mixgo.button_a')['is_pressed'] = pressed_converter('sensor_mixgo_button_is_pressed'); +pbc.moduleFunctionD.get('mixgo.button_b')['is_pressed'] = pressed_converter('sensor_mixgo_button_is_pressed'); +pbc.moduleFunctionD.get('mixgo.button_a')['was_pressed'] = pressed_converter('sensor_mixgo_button_was_pressed'); +pbc.moduleFunctionD.get('mixgo.button_b')['was_pressed'] = pressed_converter('sensor_mixgo_button_was_pressed'); + + +function getpresses_converter (mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pinType = "pins_button"; + var objblock = py2block.convert(btn); + pbc.pinType = null; + var argblock = py2block.convert(args[0]); + return block(mode, func.lineno, {}, { + "btn": objblock, + 'VAR': argblock + }, { + "inline": "true" + }); + } + return converter; +} +pbc.moduleFunctionD.get('mixgo.button_a')['get_presses'] = getpresses_converter('sensor_mixgo_button_get_presses'); +pbc.moduleFunctionD.get('mixgo.button_b')['get_presses'] = getpresses_converter('sensor_mixgo_button_get_presses'); + + +pbc.moduleFunctionD.get('mixgo.touch1')['is_touched'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pin + pbc.pinType = "number1"; + var objblock = py2block.convert(btn); + pbc.pinType = null; + return block("sensor_mixgo_pin_pressed", func.lineno, {}, { + "button":objblock + }, { + "inline": "true" + }); +} +pbc.moduleFunctionD.get('mixgo.touch2')['is_touched'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pin + pbc.pinType = "number1"; + var objblock = py2block.convert(btn); + pbc.pinType = null; + return block("sensor_mixgo_pin_pressed", func.lineno, {}, { + "button":objblock + }, { + "inline": "true" + }); +} +pbc.moduleFunctionD.get('mixgo.touch3')['is_touched'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pin + pbc.pinType = "number1"; + var objblock = py2block.convert(btn); + pbc.pinType = null; + return block("sensor_mixgo_pin_pressed", func.lineno, {}, { + "button":objblock + }, { + "inline": "true" + }); +} +pbc.moduleFunctionD.get('mixgo.touch4')['is_touched'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pin + pbc.pinType = "number1"; + var objblock = py2block.convert(btn); + pbc.pinType = null; + return block("sensor_mixgo_pin_pressed", func.lineno, {}, { + "button":objblock + }, { + "inline": "true" + }); +} + + +pbc.moduleFunctionD.get('mixgo.infrared_left')['near'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + return block("sensor_mixgo_pin_near", func.lineno, {"direction":'left'}, {}, { + "inline": "true" + }); + +} + +pbc.moduleFunctionD.get('mixgo.infrared_right')['near'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + return block("sensor_mixgo_pin_near", func.lineno, {"direction":'right'}, {}, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('near')['Infrared'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="Infrared" && mac==="mixgo"){ + + pbc.pinType = "pins_analog_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + + + return block("sensor_mixgo_extern_pin_near", func.lineno, {}, { + "PIN": pinblock, + }, { + "inline": "true" + }); +} + +} + +pbc.moduleFunctionD.get('mixgo')['get_brightness'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0 && args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + if (args.length == 0){ + return block("sensor_mixgo_light", func.lineno, {}, {}, { + "inline": "true" + }); + } + if (args.length == 1){ + pbc.pinType = "pins_analog_pin"; + var pinblock = py2block.convert(args[0]); + pbc.pinType = null; + return block("sensor_mixgo_extern_light", func.lineno, {}, { + 'PIN':pinblock + }, { + "inline": "true" + }); + } + +} + +pbc.moduleFunctionD.get('mixgo')['get_soundlevel'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0 && args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + if (args.length == 0){ + return block("sensor_sound", func.lineno, {}, {}, { + "inline": "true" + }); + } + if (args.length == 1){ + pbc.pinType = "pins_analog_pin"; + var pinblock = py2block.convert(args[0]); + pbc.pinType = null; + return block("sensor_mixgo_extern_sound", func.lineno, {}, { + 'PIN':pinblock + }, { + "inline": "true" + }); + } +} + +pbc.assignD.get('RTC')['check_assign'] = function(py2block, node, targets, value) { + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + value.args = value.args || []; + if(value._astname === "Call" && moduleName === "machine" && funcName === "RTC" && !value.args.length) + return true; + + return false; +} + +pbc.assignD.get('RTC')['create_block'] = function(py2block, node, targets, value){ + + var objblock=py2block.convert(targets[0]); + + return [block("sensor_rtc_init", node.lineno, {}, { + 'SUB':objblock + }, + { + "inline":"true" + } + )]; +} + +pbc.objectFunctionD.get('datetime')['RTC'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + /*if (keywords.length !== 0) { + throw new Error("Incorrect number of arguments"); + }*/ + if(args.length==0){ + var objblock=py2block.convert(func.value); + return block("RTC_get_time", func.lineno, {}, { + 'SUB':objblock + }, { + "inline": "true" + }); + } + else if(args.length==1&&args[0]._astname=="Tuple"){ + + var objblock=py2block.convert(func.value); + var yearblock=py2block.convert(args[0].elts[0]) + var monthblock=py2block.convert(args[0].elts[1]) + var dayblock=py2block.convert(args[0].elts[2]) + var weekdayblock=py2block.convert(args[0].elts[3]) + var hourblock=py2block.convert(args[0].elts[4]) + var minuteblock=py2block.convert(args[0].elts[5]) + var secondblock=py2block.convert(args[0].elts[6]) + var millisecondblock=py2block.convert(args[0].elts[7]) + + return [block("RTC_set_datetime", func.lineno, {}, { + 'SUB':objblock, + 'year':yearblock, + 'month':monthblock, + 'day':dayblock, + 'weekday':weekdayblock, + 'hour':hourblock, + 'minute':minuteblock, + 'second':secondblock, + 'millisecond':millisecondblock, + }, { + "inline": "false" + })]; + } + +} + +/*I2C出现了一些问题,待解决*/ +pbc.assignD.get('i2c')['check_assign'] = function (py2block, node, targets, value) { + var funcName = py2block.identifier(value.func.attr); + var moduleName = py2block.identifier(value.func.value.id); + if (value._astname === "Call" && ['MPU9250', 'SHT20', 'BMP280', 'ADXL345'].indexOf(funcName) != -1 + && ['mpu9250', 'sht20', 'bmp280', 'adxl345'].indexOf(moduleName) != -1 && value.args.length === 1) + return true; + + return false; + +} +pbc.assignD.get('i2c')['create_block'] = function (py2block, node, targets, value) { + var funcblock = py2block.identifier(value.func.attr); + var mpublock = py2block.convert(targets[0]); + var i2cblock = py2block.convert(value.args[0]); + return block("sensor_use_i2c_init", node.lineno, { "key": funcblock }, { + 'I2CSUB': i2cblock, + 'SUB': mpublock, + }, { + "inline": "true" + }); +} + + +function getAcceleration(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block('sensor_mpu9250_get_acceleration', func.lineno, { + "key": mode + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('mpu9250_get_x')['mpu'] = getAcceleration('x'); +pbc.objectFunctionD.get('mpu9250_get_y')['mpu'] = getAcceleration('y'); +pbc.objectFunctionD.get('mpu9250_get_z')['mpu'] = getAcceleration('z'); +pbc.objectFunctionD.get('mpu9250_get_values')['mpu'] = getAcceleration('values'); + +function getADXLAcceleration(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block('sensor_adxl345_get_acceleration', func.lineno, { + "key": mode + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('readX')['snsr'] = getADXLAcceleration('x'); +pbc.objectFunctionD.get('readY')['snsr'] = getADXLAcceleration('y'); +pbc.objectFunctionD.get('readZ')['snsr'] = getADXLAcceleration('z'); +pbc.objectFunctionD.get('readXYZ')['snsr'] = getADXLAcceleration('values'); + +function getMagnetic(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block('sensor_mpu9250_get_magnetic', func.lineno, { + "key": mode + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('mpu9250_magnetic_x')['mpu'] = getMagnetic('x'); +pbc.objectFunctionD.get('mpu9250_magnetic_y')['mpu'] = getMagnetic('y'); +pbc.objectFunctionD.get('mpu9250_magnetic_z')['mpu'] = getMagnetic('z'); +pbc.objectFunctionD.get('mpu9250_magnetic_values')['mpu'] = getMagnetic('values'); + +function getGyro(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block('sensor_mpu9250_get_gyro', func.lineno, { + "key": mode + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('mpu9250_gyro_x')['mpu'] = getGyro('x'); +pbc.objectFunctionD.get('mpu9250_gyro_y')['mpu'] = getGyro('y'); +pbc.objectFunctionD.get('mpu9250_gyro_z')['mpu'] = getGyro('z'); +pbc.objectFunctionD.get('mpu9250_gyro_values')['mpu'] = getGyro('values'); + +function sensorcompass(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block('sensor_mpu9250_field_strength', func.lineno, { + "compass": mode + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('mpu9250_get_field_strength')['mpu'] = sensorcompass('strength'); +pbc.objectFunctionD.get('heading')['mpu'] = sensorcompass('heading'); + +pbc.objectFunctionD.get('mpu9250_get_temperature')['mpu'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block("sensor_mpu9250_temperature", func.lineno, {}, { + 'SUB': mpublock + }, { + "inline": "true" + }); +} + +function sensorBmp(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block('sensor_bmp', func.lineno, { + "key": mode + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('get_BMP_temperature')['mpu'] = sensorBmp('get_BMP_temperature()'); +pbc.objectFunctionD.get('get_BMP_pressure')['mpu'] = sensorBmp('get_BMP_pressure()'); + +function sensorSht(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var mpublock=py2block.convert(func.value) + return block('sensor_sht', func.lineno, { + "key": mode + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('get_SHT_temperature')['mpu'] = sensorSht('get_SHT_temperature()'); +pbc.objectFunctionD.get('get_SHT_relative_humidity')['mpu'] = sensorSht('get_SHT_relative_humidity()'); + + + +function dht(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="pins_digital_pin"; + var pinblock=py2block.convert(args[1]); + pbc.pinType=null; + var dhtblock=py2block.identifier(args[0].s); + return block('sensor_dht11', func.lineno, { + 'TYPE':dhtblock, + 'WHAT':mode + }, { + "PIN":pinblock, + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.moduleFunctionD.get('dhtx')['get_dht_temperature'] = dht('temperature'); +pbc.moduleFunctionD.get('dhtx')['get_dht_relative_humidity'] = dht('relative_humidity'); +pbc.moduleFunctionD.get('dhtx')['get_dht_tempandhum'] = dht('tempandhum'); + + + +pbc.objectFunctionD.get('checkdist')['sonar'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (func.value.args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="pins_digital_pin"; + var trigblock=py2block.convert(func.value.args[0]); + var echoblock=py2block.convert(func.value.args[1]); + pbc.pinType=null; + return block("HCSR04", func.lineno, {}, { + "PIN1":trigblock, + "PIN2":echoblock + }, { + "inline": "true" + }); +} + + +pbc.objectFunctionD.get('mpu9250_is_gesture')['mpu'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var gesblock=py2block.identifier(args[0].s); + var mpublock=py2block.convert(func.value) + return block("sensor_mpu9250_gesture", func.lineno, { + 'gesture':gesblock + }, { + 'SUB': mpublock + }, { + "inline": "true" + }); +} + + +pbc.moduleFunctionD.get('mixgo.button_a')['irq'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0 || keywords.length!==2) { + throw new Error("Incorrect number of arguments"); + } + + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pinType="pins_button"; + var objblock=py2block.convert(btn); + pbc.pinType=null; + var irq=py2block.identifier(keywords[1].value.attr); + var pin=py2block.identifier(keywords[1].value.value.attr); + var mac=py2block.identifier(keywords[1].value.value.value.id) + + + var mode = mac+"."+pin+"."+py2block.identifier(keywords[1].value.attr); + + pbc.pinType = "pins_callback"; + var callback = py2block.convert(keywords[0].value); + pbc.pinType = null; + + return [block("sensor_mixgo_button_attachInterrupt", func.lineno, {"mode":mode}, { + "btn": objblock, + "DO": callback + }, { + "inline": "true" + })]; + +} + +pbc.moduleFunctionD.get('mixgo.button_b')['irq'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0 || keywords.length!==2) { + throw new Error("Incorrect number of arguments"); + } + + var btn = { + '_astname': 'Name', + 'id': { + '_astname': 'Str', + 'v': py2block.identifier(func.value.attr) + } + }; + pbc.pinType="pins_button"; + var objblock=py2block.convert(btn); + pbc.pinType=null; + var irq=py2block.identifier(keywords[1].value.attr); + var pin=py2block.identifier(keywords[1].value.value.attr); + var mac=py2block.identifier(keywords[1].value.value.value.id) + + + var mode = mac+"."+pin+"."+py2block.identifier(keywords[1].value.attr); + + pbc.pinType = "pins_callback"; + var callback = py2block.convert(keywords[0].value); + pbc.pinType = null; + + return [block("sensor_mixgo_button_attachInterrupt", func.lineno, {"mode":mode}, { + "btn": objblock, + "DO": callback + }, { + "inline": "true" + })]; + +} + +pbc.objectFunctionD.get('was_pressed')['Button'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="Button" && mac==="mixgo"){ + + pbc.pinType = "pins_digital_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + + pbc.pinType = "pins_digital"; + var argblock = py2block.convert(args[0]); + pbc.pinType = null; + + return block('sensor_mixgo_extern_button_was_pressed', func.lineno, {}, { + "PIN": pinblock, + "STAT": argblock + }, { + "inline": "true" + }); + } +} + +pbc.objectFunctionD.get('get_presses')['Button'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="Button" && mac==="mixgo"){ + + pbc.pinType = "pins_digital_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + var argblock = py2block.convert(args[0]); + return block('sensor_mixgo_extern_button_get_presses', func.lineno, {}, { + "PIN": pinblock, + 'VAR':argblock + }, { + "inline": "true" + }); + } +} + +pbc.objectFunctionD.get('is_pressed')['Button'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var pin=py2block.identifier(func.value.func.attr); + var mac=py2block.identifier(func.value.func.value.id); + if(pin==="Button" && mac==="mixgo"){ + + pbc.pinType = "pins_digital_pin"; + var pinblock = py2block.convert(func.value.args[0]); + pbc.pinType = null; + + pbc.pinType = "pins_digital"; + var argblock = py2block.convert(args[0]); + pbc.pinType = null; + + return block('sensor_mixgo_extern_button_is_pressed', func.lineno, {}, { + "PIN": pinblock, + "STAT": argblock + }, { + "inline": "true" + }); + } +} + +pbc.moduleFunctionD.get('ds18x20x')['get_ds18x20_temperature'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="pins_digital_pin"; + var argblock = py2block.convert(args[0]); + pbc.pinType = null; + return block("sensor_ds18x20", func.lineno, {}, { + "PIN":argblock, + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('calibrate')['mpu'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("sensor_mpu9250_calibrate_compass", func.lineno, {}, { + "SUB": objblock, + }, { + "inline": "true" + })]; +}; + +pbc.objectFunctionD.get('reset_calibrate')['mpu'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("sensor_compass_reset", func.lineno, {}, { + "SUB": objblock, + }, { + "inline": "true" + })]; +}; + +pbc.moduleFunctionD.get('lm35')['get_LM35_temperature'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType="pins_analog_pin"; + var argblock = py2block.convert(args[0]); + pbc.pinType = null; + return block("sensor_lm35", func.lineno, {}, { + "PIN":argblock, + }, { + "inline": "true" + }); +} diff --git a/mixly/boards/default_src/micropython/converters/serial.js b/mixly/boards/default_src/micropython/converters/serial.js new file mode 100644 index 00000000..1aab6577 --- /dev/null +++ b/mixly/boards/default_src/micropython/converters/serial.js @@ -0,0 +1,198 @@ + +pbc.globalFunctionD['print'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length === 1 && keywords.length === 1 + && py2block.identifier(keywords[0].arg) === "end" + && keywords[0].value._astname === "Str" + //&& py2block.Str_value(keywords[0].value) === "" + ){ if(py2block.Str_value(keywords[0].value) === ""){ + var argblock = py2block.convert(args[0]); + return [block("system_print_inline", func.lineno, {}, { + 'VAR':argblock + }, { + "inline": "false" + })]; + } + else{ + var argblock = py2block.convert(args[0]); + return [block("system_print_end", func.lineno, { + }, { + 'VAR':argblock, + 'END':py2block.convert(keywords[0].value) + }, { + "inline": "true" + })]; + } + }else if (args.length === 1 && keywords.length === 0) { + var argblock = py2block.convert(args[0]); + return [block("system_print", func.lineno, {}, { + 'VAR':argblock + }, { + "inline": "false" + })]; + }else if (args.length != 1 && keywords.length === 0) { //print() + var d = py2block.convertElements("ADD", args); + + return [block("system_print_many", node.lineno, { + }, d, { + "inline": "true", + }, { + "@items":args.length + })]; + + }else{ + throw new Error("Incorrect number of arguments"); + } +} + + +pbc.globalFunctionD['input'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return block("system_input", func.lineno, {}, { + 'VAR':argblock + }, { + "inline": "false" + }); +} +pbc.assignD.get('UART')['check_assign'] = function(py2block, node, targets, value) { + if(value._astname != "Call" || value.func._astname != "Attribute" || value.func.value._astname != "Name"){ + return false; + } + var moduleName = py2block.Name_str(value.func.value); + var funcName = py2block.identifier(value.func.attr); + if(value._astname === "Call" && moduleName === "machine" + && funcName === "UART" && value.args.length === 2) + return true; + return false; +} + +pbc.assignD.get('UART')['create_block'] = function(py2block, node, targets, value){ + pbc.pinType = "serial_print"; + var pinblock = py2block.identifier(value.args[0].n); + var countblock = py2block.identifier(value.args[1].n); + pbc.pinType = null; + return block("serial_softserial", node.lineno, { + "mode":pinblock, + 'baudrate':countblock + }, { }, + { + "inline":"true" + } + ); +} + +function serial_write(mode){ +function converter(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var astname = args[0]._astname; + if(astname === "Call"){ + if(args[0].func._astname == "Name" && py2block.Name_str(args[0].func) === "str"){ //serial.write(str("XXX")) + return [block("serial_print", func.lineno, { + "mode":mode + }, { + "CONTENT":py2block.convert(args[0].args[0]), + }, { + "inline": "false" + })]; + } + }else if(astname === "BinOp"){ + if(args[0].op.name === "Add" && args[0].right._astname === "Str" + && py2block.Str_value(args[0].right) === "\r\n" + && args[0].left._astname === "Call" && args[0].left.func._astname == "Name" + && py2block.Name_str(args[0].left.func) === "str" + ){ + if(args[0].left.args[0]._astname === "Call" + && args[0].left.args[0].func._astname === "Name" + && py2block.Name_str(args[0].left.args[0].func) in {"hex":16,"bin":2,"oct":8}){ + //serial.write(str(hex(XX)) + "\r\n") + pbc.inScope = "lcd_init"; + var numblock=py2block.convert(args[0].left.args[0].args[0]); + pbc.inScope=null; + return [block("serial_print_hex", func.lineno, { + "mode":mode, + "STAT":py2block.Name_str(args[0].left.args[0].func), + }, { + "CONTENT":numblock, + }, { + "inline": "true" + })]; + }else{ + return [block("serial_println", func.lineno, { + "mode":mode + }, { //serial.write(str("XX") + "\r\n") + "CONTENT": py2block.convert(args[0].left.args[0]), + }, { + "inline": "false" + })]; + } + } + } + return [block("serial_print", func.lineno, {}, { + "CONTENT":py2block.convert(args[0]), + }, { + "inline": "true" + })]; +} +return converter +} +pbc.moduleFunctionD.get('uart0')['write'] = serial_write('0') +pbc.moduleFunctionD.get('uart1')['write'] = serial_write('1') +pbc.moduleFunctionD.get('uart2')['write'] = serial_write('2') + +pbc.assignD.get('uart0')['check_assign'] = function (py2block, node, targets, value) { + var funcName = py2block.identifier(value.func.id); + if (value._astname === "Call"&& funcName === "UART" && value.args.length === 2) + return true; + return false; +} +pbc.assignD.get('uart0')['create_block'] = function (py2block, node, targets, value) { + pbc.pinType = 'serial_print'; + var argblock1 = py2block.convert(value.args[1]) + mode=targets[0].id.v + if (mode=="uart0"){ + mode='0' + } + else if(mode=="uart1"){ + mode='1' + } + else if(mode=="uart2"){ + mode='2' + } + return block("serial_softserial", node.lineno, { + "mode":mode + }, { + "CONTENT":py2block.convert(value.args[0]), + "TEXT":argblock1, + }, { + "inline": "true" + }); +} + +function getSerial(mode,fun_type){ + function converter(py2block, func, args, keywords, starargs, kwargs, node){ + if(args.length !==0){ + throw new Error("Incorrect number of arguments"); + } + return block(fun_type, func.lineno, { + "mode":mode + }, { + }, { + "inline": "true" + }); + } + return converter; +} +pbc.moduleFunctionD.get('uart0')['any'] = getSerial('0','serial_any') +pbc.moduleFunctionD.get('uart1')['any'] = getSerial('1','serial_any') +pbc.moduleFunctionD.get('uart2')['any'] = getSerial('2','serial_any') +pbc.moduleFunctionD.get('uart0')['read'] = getSerial('0','serial_readstr') +pbc.moduleFunctionD.get('uart1')['read'] = getSerial('1','serial_readstr') +pbc.moduleFunctionD.get('uart2')['read'] = getSerial('2','serial_readstr') +pbc.moduleFunctionD.get('uart0')['readline'] = getSerial('0','serial_readline') +pbc.moduleFunctionD.get('uart1')['readline'] = getSerial('1','serial_readline') +pbc.moduleFunctionD.get('uart2')['readline'] = getSerial('2','serial_readline') + diff --git a/mixly/boards/default_src/micropython/export.js b/mixly/boards/default_src/micropython/export.js new file mode 100644 index 00000000..b0afa2d5 --- /dev/null +++ b/mixly/boards/default_src/micropython/export.js @@ -0,0 +1,126 @@ +import * as MicroPythonActuatorExternBlocks from './blocks/actuator_extern'; +import * as MicroPythonActuatorOnBoardBlocks from './blocks/actuator_onboard'; +import * as MicroPythonActuatorBlocks from './blocks/actuator'; +import * as MicroPythonAISensorBlocks from './blocks/ai_sensor'; +import * as MicroPythonAIBlocks from './blocks/ai'; +import * as MicroPythonAILocalBlocks from './blocks/ai_local'; +import * as MicroPythonAICloudBlocks from './blocks/ai_cloud'; +import * as MicroPythonBlynkBlocks from './blocks/blynk'; +import * as MicroPythonCCG1Blocks from './blocks/cc_g1'; +import * as MicroPythonCEGOBlocks from './blocks/ce_go'; +import * as MicroPythonCommunicateBlocks from './blocks/communicate'; +import * as MicroPythonControlBlocks from './blocks/control'; +import * as MicroPythonDisplayExternBlocks from './blocks/display_extern'; +import * as MicroPythonDisplayOnBoardBlocks from './blocks/display_onboard'; +import * as MicroPythonDisplayBlocks from './blocks/display'; +import * as MicroPythonFactoryBlocks from './blocks/factory'; +import * as MicroPythonInputBlocks from './blocks/inout'; +import * as MicroPythonIotBlocks from './blocks/iot'; +import * as MicroPythonNetworkBlocks from './blocks/network'; +import * as MicroPythonNovaG1Blocks from './blocks/nova_g1'; +import * as MicroPythonPeG1Blocks from './blocks/pe_g1'; +import * as MicroPythonPinsBlocks from './blocks/pins'; +import * as MicroPythonSensorExternBlocks from './blocks/sensor_extern'; +import * as MicroPythonSensorOnBoardBlocks from './blocks/sensor_onboard'; +import * as MicroPythonSensorBlocks from './blocks/sensor'; +import * as MicroPythonSerialBlocks from './blocks/serial'; +import * as MicroPythonSystemBlocks from './blocks/system'; +import * as MicroPythonWeatherBlocks from './blocks/weather'; + +import * as MicroPythonActuatorExternGenerators from './generators/actuator_extern'; +import * as MicroPythonActuatorOnBoardGenerators from './generators/actuator_onboard'; +import * as MicroPythonActuatorGenerators from './generators/actuator'; +import * as MicroPythonAISensorGenerators from './generators/ai_sensor'; +import * as MicroPythonAILocalGenerators from './generators/ai_local'; +import * as MicroPythonAIGenerators from './generators/ai'; +import * as MicroPythonAICloudGenerators from './generators/ai_cloud'; +import * as MicroPythonBlynkGenerators from './generators/blynk'; +import * as MicroPythonCCG1Generators from './generators/cc_g1'; +import * as MicroPythonCEGOGenerators from './generators/ce_go'; +import * as MicroPythonCommunicateGenerators from './generators/communicate'; +import * as MicroPythonControlGenerators from './generators/control'; +import * as MicroPythonDisplayExternGenerators from './generators/display_extern'; +import * as MicroPythonDisplayOnBoardGenerators from './generators/display_onboard'; +import * as MicroPythonDisplayGenerators from './generators/display'; +import * as MicroPythonFactoryGenerators from './generators/factory'; +import * as MicroPythonInputGenerators from './generators/inout'; +import * as MicroPythonIotGenerators from './generators/iot'; +import * as MicroPythonNetworkGenerators from './generators/network'; +import * as MicroPythonNovaG1Generators from './generators/nova_g1'; +import * as MicroPythonPeG1Generators from './generators/pe_g1'; +import * as MicroPythonPinsGenerators from './generators/pins'; +import * as MicroPythonSensorExternGenerators from './generators/sensor_extern'; +import * as MicroPythonSensorOnBoardGenerators from './generators/sensor_onboard'; +import * as MicroPythonSensorGenerators from './generators/sensor'; +import * as MicroPythonSerialGenerators from './generators/serial'; +import * as MicroPythonSystemGenerators from './generators/system'; +import * as MicroPythonWeatherGenerators from './generators/weather'; + +import * as MicroPythonZhHans from './language/zh-hans'; +import * as MicroPythonZhHant from './language/zh-hant'; +import * as MicroPythonEn from './language/en'; + +import { Python } from './python_generator'; + +export { + MicroPythonActuatorExternBlocks, + MicroPythonActuatorOnBoardBlocks, + MicroPythonActuatorBlocks, + MicroPythonAISensorBlocks, + MicroPythonAIBlocks, + MicroPythonAILocalBlocks, + MicroPythonAICloudBlocks, + MicroPythonBlynkBlocks, + MicroPythonCCG1Blocks, + MicroPythonCEGOBlocks, + MicroPythonCommunicateBlocks, + MicroPythonControlBlocks, + MicroPythonDisplayExternBlocks, + MicroPythonDisplayOnBoardBlocks, + MicroPythonDisplayBlocks, + MicroPythonFactoryBlocks, + MicroPythonInputBlocks, + MicroPythonIotBlocks, + MicroPythonNetworkBlocks, + MicroPythonNovaG1Blocks, + MicroPythonPeG1Blocks, + MicroPythonPinsBlocks, + MicroPythonSensorExternBlocks, + MicroPythonSensorOnBoardBlocks, + MicroPythonSensorBlocks, + MicroPythonSerialBlocks, + MicroPythonSystemBlocks, + MicroPythonWeatherBlocks, + MicroPythonActuatorExternGenerators, + MicroPythonActuatorOnBoardGenerators, + MicroPythonActuatorGenerators, + MicroPythonAISensorGenerators, + MicroPythonAIGenerators, + MicroPythonAILocalGenerators, + MicroPythonAICloudGenerators, + MicroPythonBlynkGenerators, + MicroPythonCCG1Generators, + MicroPythonCEGOGenerators, + MicroPythonCommunicateGenerators, + MicroPythonControlGenerators, + MicroPythonDisplayExternGenerators, + MicroPythonDisplayOnBoardGenerators, + MicroPythonDisplayGenerators, + MicroPythonFactoryGenerators, + MicroPythonInputGenerators, + MicroPythonIotGenerators, + MicroPythonNetworkGenerators, + MicroPythonNovaG1Generators, + MicroPythonPeG1Generators, + MicroPythonPinsGenerators, + MicroPythonSensorExternGenerators, + MicroPythonSensorOnBoardGenerators, + MicroPythonSensorGenerators, + MicroPythonSerialGenerators, + MicroPythonSystemGenerators, + MicroPythonWeatherGenerators, + MicroPythonZhHans, + MicroPythonZhHant, + MicroPythonEn, + Python +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/actuator.js b/mixly/boards/default_src/micropython/generators/actuator.js new file mode 100644 index 00000000..5ba4c5dd --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/actuator.js @@ -0,0 +1,214 @@ +export const esp32_music_pitch = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var number_pitch = generator.valueToCode(this, 'pitch', generator.ORDER_ATOMIC); + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'music.pitch(' + pin + ', ' + number_pitch + ')\n'; + return code; +} + +export const esp32_music_pitch_with_time = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var number_pitch = generator.valueToCode(this, 'pitch', generator.ORDER_ATOMIC); + var number_time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'music.pitch_time(' + pin + ', ' + number_pitch + ', ' + number_time + ')\n'; + return code; +} + +export const esp32_music_stop = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'music.stop(' + pin + ')\n'; + return code; +} + +export const esp32_music_set_tempo = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var bpm = generator.valueToCode(this, 'BPM', generator.ORDER_ASSIGNMENT); + var ticks = generator.valueToCode(this, 'TICKS', generator.ORDER_ASSIGNMENT); + var code = "music.set_tempo(" + ticks + ", " + bpm + ")\n"; + return code; +} + +export const esp32_music_get_tempo = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var code = "music.get_tempo()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const esp32_onboard_music_pitch = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var number_pitch = generator.valueToCode(this, 'pitch', generator.ORDER_ATOMIC); + var code = 'music.pitch(' + number_pitch + ')\n'; + return code; +} + +export const esp32_onboard_music_pitch_with_time = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var number_pitch = generator.valueToCode(this, 'pitch', generator.ORDER_ATOMIC); + var number_time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + var code = 'music.pitch_time(' + number_pitch + ', ' + number_time + ')\n'; + return code; +} + +export const esp32_onboard_music_stop = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var code = 'music.stop(' + ')\n'; + return code; +} + +export const esp32_onboard_music_play_list = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var lst = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT); + var code = "music.play(" + lst + ")\n"; + return code; +} + +export const esp32_music_play_list = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var lst = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT); + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ASSIGNMENT); + var code = "music.play(" + lst + ", " + pin + ")\n"; + return code; +} + +export const esp32_mixgo_music_play_list_show = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + generator.definitions_['import_matrix'] = 'import matrix'; + var lst = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT); + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ASSIGNMENT); + // var display = generator.valueToCode(this, 'DISPLAY', generator.ORDER_ASSIGNMENT); + var code = "music.play_show(" + lst + ", " + pin + ")\n"; + return code; +} + +export const esp32_music_reset = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + return "music.reset()\n"; +} + +export const servo_move = function (_, generator) { + generator.definitions_['import_servo'] = 'import servo'; + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var value_degree = generator.valueToCode(this, 'DEGREE', generator.ORDER_ATOMIC); + var code = 'servo.servo_write_angle(' + dropdown_pin + ', ' + value_degree + ')\n'; + return code; +} + +export const number = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const ledswitch = function (_, generator) { + var code = this.getFieldValue('flag'); + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_extern_led_bright = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + // var bright = this.getFieldValue('bright'); + var code = "mixgo.led(" + pin + ").setonoff(" + bright + ")\n"; + return code; +} + +export const actuator_extern_get_led_bright = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = "mixgo.led(" + pin + ").getonoff(" + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_extern_led_brightness = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var flag = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = 'mixgo.led(' + pin + ').setbrightness(' + flag + ')\n'; + return code; +} + +export const actuator_led_bright = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + // var bright = this.getFieldValue('bright'); + var code = "mixgo.led" + op + ".setonoff(" + bright + ")\n"; + return code; +} + +export const actuator_get_led_bright = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var code = "mixgo.led" + op + ".getonoff(" + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_led_brightness = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var flag = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = 'mixgo.led' + op + '.setbrightness(' + flag + ')\n'; + return code; +} + +export const actuator_neopixel_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var dropdown_rgbpin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var value_ledcount = generator.valueToCode(this, 'LEDCOUNT', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_neopixel'] = 'import neopixel'; + var code = v + ' = neopixel.NeoPixel(machine.Pin(' + dropdown_rgbpin + '), ' + value_ledcount + ', timing=True)\n'; + return code; +} + +export const actuator_neopixel_write = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_neopixel'] = 'import neopixel'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.write()\n'; + return code; +} + +export const actuator_neopixel_rgb = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_neopixel'] = 'import neopixel'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var value_led = generator.valueToCode(this, '_LED_', generator.ORDER_ATOMIC); + var value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + var value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + var value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + var code = v + '[' + value_led + '] = (' + value_rvalue + ', ' + value_gvalue + ', ' + value_bvalue + ')\n'; + return code; +} + +export const actuator_onboard_neopixel_write = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var code = 'mixgo.rgb.write()\n'; + return code; +} + +export const actuator_onboard_neopixel_rgb = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var value_led = generator.valueToCode(this, '_LED_', generator.ORDER_ATOMIC); + var value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + var value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + var value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + var code = 'mixgo.rgb[' + value_led + '] = (' + value_rvalue + ', ' + value_gvalue + ', ' + value_bvalue + ')\n'; + return code; +} + +export const actuator_onboard_neopixel_rgb_all = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + var value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + var value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + var code = 'mixgo.rgb.fill((' + value_rvalue + ', ' + value_gvalue + ', ' + value_bvalue + '))\n'; + return code; +} + +export const led_light = actuator_led_bright; +export const get_led_bright = actuator_get_led_bright; +export const led_brightness = actuator_led_brightness; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/actuator_extern.js b/mixly/boards/default_src/micropython/generators/actuator_extern.js new file mode 100644 index 00000000..3cea0efd --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/actuator_extern.js @@ -0,0 +1,713 @@ +import { Boards } from 'mixly'; + +export const servo_init = function (_, generator) { + generator.definitions_['import_servo'] = 'import servo'; + generator.definitions_['import_board'] = 'import board'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = v + ' = servo.Servo(board.' + dropdown_pin + ')\n'; + return code; +} + +export const servo_speed_360 = function (_, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var speed = generator.valueToCode(this, 'SPEED', generator.ORDER_ATOMIC); + var code = v + '.set_speed(' + speed + ')\n'; + return code; +} + +export const servo_set_angle = function (_, generator) { + generator.definitions_['import_servo'] = 'import servo'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var code = 'servo.servo180_angle(' + dropdown_pin + ', ' + num + ')\n'; + return code; +} + +export const servo_set_speed = function (_, generator) { + generator.definitions_['import_servo'] = 'import servo'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var code = 'servo.servo360_speed(' + dropdown_pin + ', ' + num + ')\n'; + return code; +} + +export const servo_get_angle = function (_, generator) { + generator.definitions_['import_servo'] = 'import servo'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'servo.servo180_angle(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const servo_get_speed = function (_, generator) { + generator.definitions_['import_servo'] = 'import servo'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'servo.servo360_speed(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_ms32006_init = function (_, generator) { + generator.definitions_['import ms32006'] = 'import ms32006'; + var address = this.getFieldValue('mode') + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sub1 = generator.valueToCode(this, 'SUB1', generator.ORDER_ATOMIC); + var code = sub + '=ms32006.MS32006(' + sub1 + ', addr=' + address + ')\n'; + return code; +} + +export const actuator_ms32006_dcmotor = function (_, generator) { + generator.definitions_['import ms32006'] = 'import ms32006'; + var direction = this.getFieldValue('direction') + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = sub + '.dc_motor(' + direction + ', ' + speed + ')\n'; + return code; +} + +export const actuator_ms32006_stepper = function (_, generator) { + generator.definitions_['import ms32006'] = 'import ms32006'; + var mode = this.getFieldValue('mode') + var direction = this.getFieldValue('direction') + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var steps = generator.valueToCode(this, 'steps', generator.ORDER_ATOMIC); + var code = sub + '.move(' + mode + ', ' + direction + ', ' + speed + ', ' + steps + ')\n'; + return code; +} + +export const esp32_music_pitch_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var dropdown_rgbpin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + generator.definitions_['import_music'] = 'import music'; + var code = v + ' = music.MIDI(' + dropdown_rgbpin + ')\n'; + return code; +} + +export const esp32_music_pitch = function (block, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var number_pitch = generator.valueToCode(block, 'pitch', generator.ORDER_ATOMIC); + var code = v + '.pitch(' + number_pitch + ')\n'; + return code; +} + +export const esp32_music_pitch_with_time = function (block, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var number_pitch = generator.valueToCode(block, 'pitch', generator.ORDER_ATOMIC); + var number_time = generator.valueToCode(block, 'time', generator.ORDER_ATOMIC); + var code = v + '.pitch_time(' + number_pitch + ', ' + number_time + ')\n'; + return code; +} + +export const esp32_music_stop = function (block, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.stop(' + ')\n'; + return code; +} + +export const esp32_set_music_volume = function (_,generator){ + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var p = generator.valueToCode(this, 'percent', generator.ORDER_ATOMIC); + var code = v+'.set_volume('+p+')\n'; + return code; +} + +export const esp32_music_set_tempo_extern = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bpm = generator.valueToCode(this, 'BPM', generator.ORDER_ASSIGNMENT); + var ticks = generator.valueToCode(this, 'TICKS', generator.ORDER_ASSIGNMENT); + var code = v + ".set_tempo(" + ticks + ", " + bpm + ")\n"; + return code; +} + +export const esp32_music_get_tempo_extern = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + ".get_tempo()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const esp32_music_play_list = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var lst = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + ".play(" + v + '.' + lst + ")\n"; + return code; +} + +export const backstage_esp32_music_play_list = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var lst = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + ".play_thread(" + v + '.' + lst + ")\n"; + return code; +} + +export const esp32_music_reset_extern = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + return v + ".reset()\n"; +} + +export const servo_move = function (_, generator) { + generator.definitions_['import_servo'] = 'import servo'; + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var value_degree = generator.valueToCode(this, 'DEGREE', generator.ORDER_ATOMIC); + var code = 'servo.servo_write_angle(' + dropdown_pin + ', ' + value_degree + ')\n'; + return code; +} + +export const actuator_extern_led_bright = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + // var bright = this.getFieldValue('bright'); + var code = "mixgo.LED(" + pin + ").setonoff(" + bright + ")\n"; + return code; +} + +export const actuator_extern_get_led_bright = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = "mixgo.LED(" + pin + ").getbrightness(" + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_extern_get_led_state = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = "mixgo.LED(" + pin + ").getonoff(" + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_extern_led_brightness = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var flag = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = 'mixgo.LED(' + pin + ').setbrightness(' + flag + ')\n'; + return code; +} + +export const actuator_neopixel_init = function (_, generator) { + const v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + const dropdown_rgbpin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + const value_ledcount = generator.valueToCode(this, 'LEDCOUNT', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ws2812_Neopixel'] = 'from ws2812 import NeoPixel'; + const code = `${v} = NeoPixel(machine.Pin(${dropdown_rgbpin}), ${value_ledcount})\n`; + return code; +} + +export const actuator_neopixel_rgb_all = function (_, generator) { + const v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + const value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + const value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + const value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + const code = `${v}.fill((${value_rvalue}, ${value_gvalue}, ${value_bvalue}))\n`; + return code; +} + +export const actuator_neopixel_write = function (_, generator) { + const v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + const code = `${v}.write()\n`; + return code; +} + +export const actuator_neopixel_rgb = function (_, generator) { + const v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + const value_led = generator.valueToCode(this, '_LED_', generator.ORDER_ATOMIC); + const value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + const value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + const value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + const code = `${v}[${value_led}] = (${value_rvalue}, ${value_gvalue}, ${value_bvalue})\n`; + return code; +} + +export const actuator_neopixel_rgb_show_all_chase = function (_, generator) { + const v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + const value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + const value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + const value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + const number_time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + const code = `${v}.color_chase(${value_rvalue}, ${value_gvalue}, ${value_bvalue}, ${number_time})\n`; + return code; +} + +export const actuator_neopixel_rgb_show_all_rainbow = function (_, generator) { + const v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + const number_time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + const code = `${v}.rainbow_cycle(${number_time})\n`; + return code; +} + +export const actuator_use_uart_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var key2 = this.getFieldValue('key2'); + if (key2 == 'SYN6288') { + generator.definitions_['import_syn6288'] = 'import syn6288'; + var code = v + '=syn6288.SYN6288(' + key + ')\n'; + return code; + } else if (key2 == 'NS9300') { + generator.definitions_['import_ns9300'] = 'import ns9300'; + var code = v + '=ns9300.NS9300(' + key + ')\n'; + return code; + } +} + +export const player_whether_stop = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = v + '.status(' + key + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const player_set_play = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = v + '.control(' + key + ')\n'; + return code; +} + +export const player_set_volume = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var vol = generator.valueToCode(this, 'volume', generator.ORDER_ATOMIC); + var code = v + '.volume(' + vol + ')\n'; + return code; +} + +export const player_set_mode = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = v + '.mode(' + key + ')\n'; + return code; +} + +export const player_play_music = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var s = generator.valueToCode(this, 'song', generator.ORDER_ATOMIC); + var code = v + '.' + key + '(' + s + ')\n'; + return code; +} + +export const syn6288_set_voice = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var voice = generator.valueToCode(this, 'VOICE', generator.ORDER_ASSIGNMENT); + var code = v + ".volume(" + voice + ")\n"; + return code; +} + +export const syn6288_get_voice = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + ".volume()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const syn6288_builtin_voice = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('mode'); + var voice = generator.valueToCode(this, 'VOICE', generator.ORDER_ASSIGNMENT); + var code = v + ".hint_tones(" + voice + ', blocking=' + mode + ")\n"; + return code; +} + +export const syn6288_tts_play = function (_, generator) { + generator.definitions_['import_music'] = 'import music'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('mode'); + var voice = generator.valueToCode(this, 'VOICE', generator.ORDER_ASSIGNMENT); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".synthesis(" + data + ', music=' + voice + ', blocking=' + mode + ")\n"; + return code; +} + +//mixbot extern below: +export const mixbot_addr_extern = function (_, generator) { + var code = this.getFieldValue('PIN'); + return [code, generator.ORDER_ATOMIC]; +} + +export const robot_motor_extern = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_motor'] = 'from mixbot_ext import ext_motor'; + var code = 'ext_motor.run(' + mode + ',' + speed + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_motor'] = 'ext_motor_left = i2cdevice.Motor(ext_i2c_left)'; + var code = 'ext_motor_left.run(0,' + speed + ')\n'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_motor'] = 'ext_motor_right = i2cdevice.Motor(ext_i2c_right)'; + var code = 'ext_motor_right.run(0,' + speed + ')\n'; + } + return code; + } +} + +export const robot_motor_extern_get_speed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + if (version == 'mixbot') { + var code = 'ext_motor.run(' + mode + ")"; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_motor'] = 'ext_motor_left = i2cdevice.Motor(ext_i2c_left)'; + var code = 'ext_motor_left.run()'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_motor'] = 'ext_motor_right = i2cdevice.Motor(ext_i2c_right)'; + var code = 'ext_motor_right.run()'; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_traffic_light_extern = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var light = this.getFieldValue('light'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_traffic'] = 'from mixbot_ext import ext_traffic'; + var mode = this.getFieldValue('mode'); + var light = this.getFieldValue('light'); + var code = 'ext_traffic.led(' + mode + ', '; + if (light == '0' || light == '1' || light == '2') { code += '0' + ', ' } + else if (light == '3' || light == '4') { code += '1' + ',' } + else if (light == '5' || light == '6') { code += '2' + ',' } + if (light == '0') { code += '0' } + else if (light == '1' || light == '3' || light == '5') { code += '1' } + else if (light == '2' || light == '4' || light == '6') { code += '-1' } + code += ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_traffic'] = 'ext_traffic_left = i2cdevice.Traffic_LED(ext_i2c_left)'; + var code = 'ext_traffic_left.led(0,'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_traffic'] = 'ext_traffic_right = i2cdevice.Traffic_LED(ext_i2c_right)'; + var code = 'ext_traffic_right.led(0,'; + } + if (light == '0' || light == '1' || light == '2') { code += '0' + ',' } + else if (light == '3' || light == '4') { code += '1' + ',' } + else if (light == '5' || light == '6') { code += '2' + ',' } + if (light == '0') { code += '0' } + else if (light == '1' || light == '3' || light == '5') { code += '1' } + else if (light == '2' || light == '4' || light == '6') { code += '-1' } + code += ")\n"; + return code; + } +} + +export const robot_led_extern = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var color = this.getFieldValue('color'); + var value = generator.valueToCode(this, 'value', generator.ORDER_ATOMIC); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_' + color + '_LED'] = 'from mixbot_ext import ' + color + '_LED'; + var code = color + '_LED.brightness(' + mode + ', ' + value + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_' + color + '_LED'] = 'ext_' + color + '_LED_left = i2cdevice.' + color + '_LED(ext_i2c_left)'; + var code = 'ext_' + color + '_LED_left.brightness(' + '0, ' + value + ")\n"; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_' + color + '_LED'] = 'ext_' + color + '_LED_right = i2cdevice.' + color + '_LED(ext_i2c_right)'; + var code = 'ext_' + color + '_LED_right.brightness(' + '0, ' + value + ")\n"; + } + return code; + } +} + +export const robot_led_extern_get_value = function (_, generator) { + var mode = this.getFieldValue('mode'); + var color = this.getFieldValue('color'); + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_' + color + '_LED'] = 'from mixbot_ext import ' + color + '_LED'; + var code = color + '_LED.brightness(' + mode + ")"; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_' + color + '_LED'] = 'ext_' + color + '_LED_left = i2cdevice.' + color + '_LED(ext_i2c_left)'; + var code = 'ext_' + color + '_LED_left.brightness(0)'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_' + color + '_LED'] = 'ext_' + color + '_LED_right = i2cdevice.' + color + '_LED(ext_i2c_right)'; + var code = 'ext_' + color + '_LED_right.brightness(0)'; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_servo_extern_get_status = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var status = this.getFieldValue('status'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_servo'] = 'from mixbot_ext import ext_servo'; + var code = 'ext_servo.state(' + mode + ")" + status; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_servo'] = 'ext_servo_left = i2cdevice.Motor_servo(ext_i2c_left)'; + var code = 'ext_servo_left.state(0)' + status; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_servo'] = 'ext_servo_right = i2cdevice.Motor_servo(ext_i2c_right)'; + var code = 'ext_servo_right.state(0)' + status; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_servo_extern_stop_mode = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var status = this.getFieldValue('status'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_servo'] = 'from mixbot_ext import ext_servo'; + var code = 'ext_servo.stop_mode(' + mode + ", " + status + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left=i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_servo'] = 'ext_servo_left = i2cdevice.Motor_servo(ext_i2c_left)'; + var code = 'ext_servo_left.stop_mode(' + "0, " + status + ")\n"; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_servo'] = 'ext_servo_right = i2cdevice.Motor_servo(ext_i2c_right)'; + var code = 'ext_servo_right.stop_mode(' + "0, " + status + ")\n"; + } + return code; + } +} + +export const robot_servo_extern_stop = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_servo'] = 'from mixbot_ext import ext_servo'; + var code = 'ext_servo.stop(' + mode + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_servo'] = 'ext_servo_left = i2cdevice.Motor_servo(ext_i2c_left)'; + var code = 'ext_servo_left.stop(0)\n'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_servo'] = 'ext_servo_right = i2cdevice.Motor_servo(ext_i2c_right)'; + var code = 'ext_servo_right.stop(0)\n'; + } + return code; + } +} + +export const robot_servo_extern_absolute_run = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var status = this.getFieldValue('status'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var direction = this.getFieldValue('direction'); + var angle = generator.valueToCode(this, 'angle', generator.ORDER_ATOMIC); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_servo'] = 'from mixbot_ext import ext_servo'; + var code = 'ext_servo.absolute_run(' + mode + ", " + status + ", " + speed + ", " + direction + ", " + angle + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_servo'] = 'ext_servo_left = i2cdevice.Motor_servo(ext_i2c_left)'; + var code = 'ext_servo_left.absolute_run(' + "0, " + status + ", " + speed + ", " + direction + ", " + angle + ")\n"; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_servo'] = 'ext_servo_right = i2cdevice.Motor_servo(ext_i2c_right)'; + var code = 'ext_servo_right.absolute_run(' + "0, " + status + ", " + speed + ", " + direction + ", " + angle + ")\n"; + } + return code; + } +} + +export const robot_servo_extern_relative_origin = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_servo'] = 'from mixbot_ext import ext_servo'; + var code = 'ext_servo.relative_origin(' + mode + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_servo'] = 'ext_servo_left = i2cdevice.Motor_servo(ext_i2c_left)'; + var code = 'ext_servo_left.relative_origin(0)\n'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_servo'] = 'ext_servo_right = i2cdevice.Motor_servo(ext_i2c_right)'; + var code = 'ext_servo_right.relative_origin(0)\n'; + } + return code; + } +} + +export const robot_servo_extern_relative_run = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var status = this.getFieldValue('status'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var angle = generator.valueToCode(this, 'angle', generator.ORDER_ATOMIC); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_servo'] = 'from mixbot_ext import ext_servo'; + var code = 'ext_servo.relative_run(' + mode + ", " + status + ", " + speed + ", " + angle + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_servo'] = 'ext_servo_left = i2cdevice.Motor_servo(ext_i2c_left)'; + var code = 'ext_servo_left.relative_run(' + "0, " + status + ", " + speed + ", " + angle + ")\n"; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_servo'] = 'ext_servo_right = i2cdevice.Motor_servo(ext_i2c_right)'; + var code = 'ext_servo_right.relative_run(' + "0, " + status + ", " + speed + ", " + angle + ")\n"; + } + return code; + } +} + +export const robot_servo_extern_relative_continue = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var status = this.getFieldValue('status'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var direction = this.getFieldValue('direction'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_servo'] = 'from mixbot_ext import ext_servo'; + var code = 'ext_servo.relative_continue(' + mode + ", " + status + ", " + speed + ", " + direction + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_servo'] = 'ext_servo_left = i2cdevice.Motor_servo(ext_i2c_left)'; + var code = 'ext_servo_left.relative_continue(' + "0, " + status + ", " + speed + ", " + direction + ")\n"; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_servo'] = 'ext_servo_right = i2cdevice.Motor_servo(ext_i2c_right)'; + var code = 'ext_servo_right.relative_continue(' + "0, " + status + ", " + speed + ", " + direction + ")\n"; + } + return code; + } +} + +export const mixbot_actuator_extern_get_addr = function (_, generator) { + var name = this.getFieldValue('name'); + generator.definitions_['import_mixbot_ext_' + name] = 'from mixbot_ext import ' + name; + var code = name + '.addr_get()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixbot_actuator_extern_set_addr = function (_, generator) { + var name = this.getFieldValue('name'); + generator.definitions_['import_mixbot_ext_' + name] = 'from mixbot_ext import ' + name; + var oldaddr = generator.valueToCode(this, 'old', generator.ORDER_ATOMIC); + var newaddr = generator.valueToCode(this, 'new', generator.ORDER_ATOMIC); + var code = name + '.addr_set(' + oldaddr + ', ' + newaddr + ')\n'; + return code; +} + +//educore +export const PIN_init = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'pin'] = 'from ' + version + ' import pin'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'pin(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const pin_led_bright = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var pin = generator.valueToCode(this, 'pin', generator.ORDER_ATOMIC); + generator.definitions_['import_' + version + 'pin'] = 'from ' + version + ' import pin'; + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = pin + ".write_digital(value=" + bright + ")\n"; + return code; +} + +export const servo_PIN_init = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'servo'] = 'from ' + version + ' import servo'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'servo(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const servo_move_angle = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'servo'] = 'from ' + version + ' import servo'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var a = generator.valueToCode(this, 'angle', generator.ORDER_ATOMIC); + var code = sub + '.angle(' + a + ')\n'; + return code; +} + +export const parrot_PIN_init = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'parrot'] = 'from ' + version + ' import parrot'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'parrot(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const parrot_move_speed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'parrot'] = 'from ' + version + ' import parrot'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = sub + '.speed(' + speed + ')\n'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/actuator_onboard.js b/mixly/boards/default_src/micropython/generators/actuator_onboard.js new file mode 100644 index 00000000..d5619051 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/actuator_onboard.js @@ -0,0 +1,837 @@ +import { Boards } from 'mixly'; + +export const esp32_music_set_tempo = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var bpm = generator.valueToCode(this, 'BPM', generator.ORDER_ASSIGNMENT); + var ticks = generator.valueToCode(this, 'TICKS', generator.ORDER_ASSIGNMENT); + var code = "onboard_music.set_tempo(" + ticks + ", " + bpm + ")\n"; + return code; +} + +export const esp32_music_get_tempo = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var code = "onboard_music.get_tempo()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const esp32_onboard_music_pitch = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var number_pitch = generator.valueToCode(block, 'pitch', generator.ORDER_ATOMIC); + var code = 'onboard_music.pitch(' + number_pitch + ')\n'; + return code; +} + +export const esp32_onboard_music_pitch_with_time = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var number_pitch = generator.valueToCode(block, 'pitch', generator.ORDER_ATOMIC); + var number_time = generator.valueToCode(block, 'time', generator.ORDER_ATOMIC); + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_spk_midi'] = "from mixgo_zero_voice import spk_midi"; + var code = 'spk_midi.pitch_time(' + number_pitch + ', ' + number_time + ')\n'; + } else if (version == 'mixgo_nova') { + generator.definitions_['import_mixgo_nova_voice_spk_midi'] = "from mixgo_nova_voice import spk_midi"; + var code = 'spk_midi.pitch_time(' + number_pitch + ', ' + number_time + ')\n'; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_spk_midi'] = "from mixgo_soar_voice import spk_midi"; + var code = 'spk_midi.pitch_time(' + number_pitch + ', ' + number_time + ')\n'; + } else { + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var code = 'onboard_music.pitch_time(' + number_pitch + ', ' + number_time + ')\n'; + } + return code; +} + +export const esp32_onboard_music_stop = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var code = 'onboard_music.stop(' + ')\n'; + return code; +} + +export const esp32_onboard_music_play_list = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var lst = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT); + if (version == 'mixgo_sant') { + generator.definitions_['import_mixgo_sant_onboard_music'] = "from mixgo_sant import onboard_music"; + var code = "onboard_music.play(" + lst + ")\n"; + } else if (version == 'mixgo_nova') { + generator.definitions_['import_mixgo_nova_voice_spk_midi'] = "from mixgo_nova_voice import spk_midi"; + var code = "spk_midi.play(" + lst + ")\n"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_spk_midi'] = "from mixgo_soar_voice import spk_midi"; + var code = "spk_midi.play(" + lst + ")\n"; + } else { + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var code = "onboard_music.play(" + lst + ")\n"; + } + return code; +} + +export const backstage_onboard_music_play_list = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var lst = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT); + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var code = "onboard_music.play_thread(" + lst + ")\n"; + return code; +} + +export const esp32_music_reset = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + return "onboard_music.reset()\n"; +} + +export const number = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const ledswitch = function (_, generator) { + var code = this.getFieldValue('flag'); + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_led_bright = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + if (version == 'mixgo'){ + if(op == 1){ + generator.definitions_['import_' + version + 'led1'] = 'from ' + version + ' import led1'; + var code = "led1.setonoff(" + bright + ")\n"; + }else if (op == 2){ + generator.definitions_['import_' + version + 'led2'] = 'from ' + version + ' import led2'; + var code = "led2.setonoff("+ bright + ")\n"; + } + }else{ + generator.definitions_['import_' + version + '_onboard_led'] = 'from ' + version + ' import onboard_led'; + var code = "onboard_led.setonoff(" + op + "," + bright + ")\n"; + } + return code; +} + +export const actuator_get_led_bright = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + if (version == 'mixgo'){ + if(op == 1){ + generator.definitions_['import_' + version + 'led1'] = 'from ' + version + ' import led1'; + var code = "led1.getbrightness()"; + }else if (op == 2){ + generator.definitions_['import_' + version + 'led2'] = 'from ' + version + ' import led2'; + var code = "led2.getbrightness()"; + } + }else{ + generator.definitions_['import_' + version + '_onboard_led'] = 'from ' + version + ' import onboard_led'; + var code = "onboard_led.getbrightness(" + op + ")"; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_get_led_state = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + if (version == 'mixgo'){ + if(op == 1){ + generator.definitions_['import_' + version + 'led1'] = 'from ' + version + ' import led1'; + var code = "led1.getonoff()"; + }else if (op == 2){ + generator.definitions_['import_' + version + 'led2'] = 'from ' + version + ' import led2'; + var code = "led2.getonoff()"; + } + }else{ + generator.definitions_['import_' + version + '_onboard_led'] = 'from ' + version + ' import onboard_led'; + var code = "onboard_led.getonoff(" + op + ")"; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_led_brightness = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var flag = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + if (version == 'mixgo'){ + if(op == 1){ + generator.definitions_['import_' + version + 'led1'] = 'from ' + version + ' import led1'; + var code = "led1.setbrightness("+ flag + ")\n"; + }else if (op == 2){ + generator.definitions_['import_' + version + 'led2'] = 'from ' + version + ' import led2'; + var code = "led2.setbrightness("+ flag + ")\n"; + } + }else{ + generator.definitions_['import_' + version + '_onboard_led'] = 'from ' + version + ' import onboard_led'; + var code = "onboard_led.setbrightness(" + op + ", " + flag + ")\n"; + } + return code; +} + +export const actuator_mixgo_zero_led_color = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + generator.definitions_['import_' + version + '_onboard_led'] = 'from ' + version + ' import onboard_led'; + var color = this.getFieldValue('colorvalue'); + var code = "onboard_led.setcolor(" + op + ", " + color + ")\n"; + return code; +} + +export const cc_number = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const rm_actuator_led_bright = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = this.getFieldValue('color'); + generator.definitions_['import_' + version + '_' + op + 'led'] = 'from ' + version + ' import ' + op + 'led'; + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = op + "led.setonoff(" + bright + ")\n"; + return code; +} + +export const rm_actuator_get_led_bright = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = this.getFieldValue('color'); + generator.definitions_['import_' + version + '_' + op + 'led'] = 'from ' + version + ' import ' + op + 'led'; + var code = op + "led.getbrightness()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const rm_actuator_get_led_state = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = this.getFieldValue('color'); + generator.definitions_['import_' + version + '_' + op + 'led'] = 'from ' + version + ' import ' + op + 'led'; + var code = op + "led.getonoff()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const rm_actuator_led_brightness = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var op = this.getFieldValue('color'); + generator.definitions_['import_' + version + '_' + op + 'led'] = 'from ' + version + ' import ' + op + 'led'; + var flag = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = op + "led.setbrightness(" + flag + ")\n"; + return code; +} + +export const actuator_onboard_neopixel_write = function (_, generator) { + const version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_[`import_${version}_onboard_rgb`] = `from ${version} import onboard_rgb`; + const code = 'onboard_rgb.write()\n'; + return code; +} + +export const actuator_onboard_neopixel_rgb = function (_, generator) { + const version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_[`import_${version}_onboard_rgb`] = `from ${version} import onboard_rgb`; + const value_led = generator.valueToCode(this, '_LED_', generator.ORDER_ATOMIC); + const value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + const value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + const value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + const code = `onboard_rgb[${value_led}] = (${value_rvalue}, ${value_gvalue}, ${value_bvalue})\n`; + return code; +} + +export const actuator_onboard_neopixel_rgb_all = function (_, generator) { + const version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_[`import_${version}_onboard_rgb`] = `from ${version} import onboard_rgb`; + const value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + const value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + const value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + const code = `onboard_rgb.fill((${value_rvalue}, ${value_gvalue}, ${value_bvalue}))\n`; + return code; +} + +export const actuator_onboard_neopixel_rgb_show_all_chase = function (_, generator) { + const version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_[`import_${version}_onboard_rgb`] = `from ${version} import onboard_rgb`; + const value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + const value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + const value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + const number_time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + const code = `onboard_rgb.color_chase(${value_rvalue}, ${value_gvalue}, ${value_bvalue}, ${number_time})\n`; + return code; +} + +export const actuator_onboard_neopixel_rgb_show_all_rainbow = function (_, generator) { + const version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_[`import_${version}_onboard_rgb`] = `from ${version} import onboard_rgb`; + const number_time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + const code = `onboard_rgb.rainbow_cycle(${number_time})\n`; + return code; +} + +export const rm_motor = function (_, generator) { + var wheel = this.getFieldValue('wheel'); + generator.definitions_['import_rm_e1_motor' + wheel] = 'from rm_e1 import motor' + wheel; + var v = this.getFieldValue('direction'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = "motor" + wheel + '.motion("' + v + '",' + speed + ")\n"; + return code; +} + +//c3 motor onboard +export const actuator_stepper_keep = function (_, generator) { + var v = this.getFieldValue('VAR'); + generator.definitions_['import_mixgocar_c3_car'] = 'from mixgocar_c3 import car'; + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT); + var code = 'car.motor_move("' + v + '",' + speed + ")\n"; + return code; +} + +export const actuator_stepper_stop = function (_, generator) { + var v = this.getFieldValue('VAR'); + generator.definitions_['import_mixgocar_c3_car'] = 'from mixgocar_c3 import car'; + var code = 'car.motor_move("' + v + '"' + ")\n"; + return code; +} + +export const actuator_dc_motor = function (_, generator) { + var wheel = this.getFieldValue('wheel'); + generator.definitions_['import_mixgocar_c3_car'] = 'from mixgocar_c3 import car'; + var v = this.getFieldValue('direction'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = "car.motor(car.MOTO_" + wheel + ', "' + v + '", ' + speed + ")\n"; + return code; +} + +export const actuator_dc_motor_stop = function (_, generator) { + var wheel = this.getFieldValue('wheel'); + generator.definitions_['import_mixgocar_c3_car'] = 'from mixgocar_c3 import car'; + var v = this.getFieldValue('direction'); + var code = "car.motor(car.MOTO_" + wheel + ', "' + v + '"' + ")\n"; + return code; +} + +//mixbot onboard_motor below: + +export const mixbot_motor_status = function (_, generator) { + generator.definitions_['import_mixbot_motor'] = 'from mixbot import motor'; + var code = 'motor.status()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixbot_move = function (_, generator) { + var v = this.getFieldValue('VAR'); + var mode = this.getFieldValue('mode'); + generator.definitions_['import_mixbot_motor'] = 'from mixbot import motor'; + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT); + var code = 'motor.move("' + v + '", motor.' + mode + '_MODE,' + speed + ")\n"; + return code; +} + +export const mixbot_stop = function (_, generator) { + var v = this.getFieldValue('VAR'); + generator.definitions_['import_mixbot_motor'] = 'from mixbot import motor'; + if (v == 'N') { + var code = 'motor.move("N", motor.STOP_MODE)\n' + } else if (v == 'P') { + var code = 'motor.move("P", motor.BRAKE_MODE)\n' + } + return code; +} + +export const mixbot_motor = function (_, generator) { + var wheel = this.getFieldValue('wheel'); + generator.definitions_['import_mixbot_motor'] = 'from mixbot import motor'; + var mode = this.getFieldValue('mode'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = 'motor.run(' + wheel + ', motor.' + mode + '_MODE, ' + speed + ")\n"; + return code; +} + +export const actuator_mixbot_buzzer_on_off = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_spk_en'] = 'from ' + version + ' import spk_en'; + var op = this.getFieldValue('on_off'); + var code = "spk_en.value(" + op + ")\n"; + return code; +} + +//bitbot onboard_motor below: +export const bitbot_move = function (_, generator) { + var v = this.getFieldValue('VAR'); + generator.definitions_['import_feiyi_onboard_bot51'] = 'from feiyi import onboard_bot51'; + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT); + var code = 'onboard_bot51.move("' + v + '", ' + speed + ")\n"; + return code; +} + +export const bitbot_stop = function (_, generator) { + var v = this.getFieldValue('VAR'); + generator.definitions_['import_feiyi_onboard_bot51'] = 'from feiyi import onboard_bot51'; + var code = 'onboard_bot51.move("' + v + '"' + ")\n"; + return code; +} + +export const bitbot_motor = function (_, generator) { + var wheel = this.getFieldValue('wheel'); + var direction = this.getFieldValue('direction'); + generator.definitions_['import_feiyi_onboard_bot51'] = 'from feiyi import onboard_bot51'; + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = 'onboard_bot51.motor(' + wheel + ', "' + direction + '", ' + speed + ")\n"; + return code; +} + +export const actuator_mixgo_nova_mic_set = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_ob_code'] = "from mixgo_zero_voice import ob_code"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_ob_code'] = "from mixgo_soar_voice import ob_code"; + } else { + generator.definitions_['import_mixgo_nova_voice_ob_code'] = "from mixgo_nova_voice import ob_code"; + } + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = "ob_code.mic_volume(" + bright + ")\n"; + return code; +} + +export const actuator_mixgo_nova_mic_get = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_ob_code'] = "from mixgo_zero_voice import ob_code"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_ob_code'] = "from mixgo_soar_voice import ob_code"; + } else { + generator.definitions_['import_mixgo_nova_voice_ob_code'] = "from mixgo_nova_voice import ob_code"; + } + var code = "ob_code.mic_volume()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_mixgo_nova_voice_set = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_ob_code'] = "from mixgo_zero_voice import ob_code"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_ob_code'] = "from mixgo_soar_voice import ob_code"; + } else { + generator.definitions_['import_mixgo_nova_voice_ob_code'] = "from mixgo_nova_voice import ob_code"; + } + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = "ob_code.voice_volume(" + bright + ")\n"; + return code; +} + +export const actuator_mixgo_nova_voice_get = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_ob_code'] = "from mixgo_zero_voice import ob_code"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_ob_code'] = "from mixgo_soar_voice import ob_code"; + } else { + generator.definitions_['import_mixgo_nova_voice_ob_code'] = "from mixgo_nova_voice import ob_code"; + } + var code = "ob_code.voice_volume()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const actuator_mixgo_nova_record_audio = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_record_audio'] = "from mixgo_zero_voice import record_audio"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_record_audio'] = "from mixgo_soar_voice import record_audio"; + } else { + generator.definitions_['import_mixgo_nova_voice_record_audio'] = "from mixgo_nova_voice import record_audio"; + } + var path = generator.valueToCode(this, 'PATH', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'TIME', generator.ORDER_ASSIGNMENT); + var code = "record_audio(" + path + ", " + time + ")\n"; + return code; +} + +export const actuator_mixgo_nova_play_audio = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_play_audio'] = "from mixgo_zero_voice import play_audio"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_play_audio'] = "from mixgo_soar_voice import play_audio"; + } else { + generator.definitions_['import_mixgo_nova_voice_play_audio'] = "from mixgo_nova_voice import play_audio"; + } + var path = generator.valueToCode(this, 'PATH', generator.ORDER_ASSIGNMENT); + var code = "play_audio(" + path + ")\n"; + return code; +} + +export const actuator_mixgo_nova_play_online_audio = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_play_audio_url'] = "from mixgo_zero_voice import play_audio_url"; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_play_audio_url'] = "from mixgo_soar_voice import play_audio_url"; + } else { + generator.definitions_['import_mixgo_nova_voice_play_audio_url'] = "from mixgo_nova_voice import play_audio_url"; + } + var path = generator.valueToCode(this, 'PATH', generator.ORDER_ASSIGNMENT); + var code = "play_audio_url(" + path + ")\n"; + return code; +} + +export const actuator_mixgo_nova_onboard_music_pitch = function (block, generator) { + generator.definitions_['import_mixgo_nova_voice_spk_midi'] = "from mixgo_nova_voice import spk_midi"; + var number_pitch = generator.valueToCode(block, 'pitch', generator.ORDER_ATOMIC); + var code = 'spk_midi.pitch(' + number_pitch + ')\n'; + return code; +} + +export const actuator_mixgo_nova_onboard_music_stop = function (block, generator) { + generator.definitions_['import_mixgo_nova_voice_spk_midi'] = "from mixgo_nova_voice import spk_midi"; + var code = 'spk_midi.stop(' + ')\n'; + return code; +} + +export const set_power_output = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var index = this.getFieldValue('index'); + var duty = generator.valueToCode(this, 'duty', generator.ORDER_ATOMIC); + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.usben(' + index + ', ' + duty + ')\n'; + return code; +} + +export const get_power_output = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var index = this.getFieldValue('index'); + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.usben(' + index + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const set_all_power_output = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var duty = generator.valueToCode(this, 'duty', generator.ORDER_ATOMIC); + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.usben(freq=' + duty + ')\n'; + return code; +} + +export const set_part_power_output = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var index = this.getFieldValue('index'); + var duty = generator.valueToCode(this, 'duty', generator.ORDER_ATOMIC); + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.usben(' + index + ', freq=' + duty + ')\n'; + return code; +} + +export const analog_keyboard_input = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var sp = generator.valueToCode(this, 'special', generator.ORDER_ATOMIC); + var ge = generator.valueToCode(this, 'general', generator.ORDER_ATOMIC); + var re = this.getFieldValue('release'); + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = "onboard_bot.hid_keyboard(" + sp + ", " + ge + ", " + re + ")\n"; + return code; +} + +export const special_key = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const general_key = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const analog_mouse_input = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var wheel = generator.valueToCode(this, 'wheel', generator.ORDER_ATOMIC); + var re = this.getFieldValue('release'); + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = "onboard_bot.hid_mouse(keys=" + key + ", move=(" + x + ", " + y + "), wheel=" + wheel + ", release=" + re + ")\n"; + return code; +} + +export const mouse_key = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const analog_keyboard_str = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var str = generator.valueToCode(this, 'str', generator.ORDER_ATOMIC); + var t = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = "onboard_bot.hid_keyboard_str(" + str + ", delay=" + t + ")\n"; + return code; +} + +export const general_key_tuple = function (_, generator) { + // Create a list with any number of elements of any type. + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + if (this.itemCount_ != 1) { + var code = '(' + code.join(', ') + ')'; + } else { + var code = '(' + code.join(', ') + ',)'; + } + + return [code, generator.ORDER_ATOMIC]; +}; + +export const analog_ble_keyboard_init = function (_, generator) { + generator.definitions_['import_ble_keyboard'] = 'from ble_hid_keyboard import Keyboard'; + var kname = generator.valueToCode(this, 'kname', generator.ORDER_ATOMIC) + var code = 'ble_keyboard=Keyboard(' + kname + ')\n'; + return code; +} + +export const ble_keyboard_get_mac = function (_, generator) { + generator.definitions_['import_ble_keyboard'] = 'from ble_hid_keyboard import Keyboard'; + var code = 'ble_keyboard.mac'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ble_keyboard_connect = function (_, generator) { + generator.definitions_['import_ble_keyboard'] = 'from ble_hid_keyboard import Keyboard'; + var code = 'ble_keyboard.is_connected()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const analog_ble_keyboard_input = function (_, generator) { + var sp = generator.valueToCode(this, 'special', generator.ORDER_ATOMIC); + var ge = generator.valueToCode(this, 'general', generator.ORDER_ATOMIC); + var re = this.getFieldValue('release'); + generator.definitions_['import_ble_keyboard'] = 'from ble_hid_keyboard import Keyboard'; + var code = "ble_keyboard.notify_hid(" + sp + ", " + ge + ", " + re + ")\n"; + return code; +} + +export const analog_ble_keyboard_str = function (_, generator) { + var str = generator.valueToCode(this, 'str', generator.ORDER_ATOMIC); + var t = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + generator.definitions_['import_ble_keyboard'] = 'from ble_hid_keyboard import Keyboard'; + var code = "ble_keyboard.notify_str(" + str + ", delay=" + t + ")\n"; + return code; +} + +export const analog_ble_keyboard_send_battery = function (_, generator) { + var b = generator.valueToCode(this, 'battery', generator.ORDER_ATOMIC); + generator.definitions_['import_ble_keyboard'] = 'from ble_hid_keyboard import Keyboard'; + var code = "ble_keyboard.notify_battery(" + b + ")\n"; + return code; +} + +export const analog_ble_mouse_init = function (_, generator) { + generator.definitions_['import_ble_mouse'] = 'from ble_hid_mouse import Mouse'; + var name = generator.valueToCode(this, 'name', generator.ORDER_ATOMIC) + var code = 'ble_mouse=Mouse(' + name + ')\n'; + return code; +} + +export const ble_mouse_get_mac = function (_, generator) { + generator.definitions_['import_ble_mouse'] = 'from ble_hid_mouse import Mouse'; + var code = 'ble_mouse.mac'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ble_mouse_connect = function (_, generator) { + generator.definitions_['import_ble_mouse'] = 'from ble_hid_mouse import Mouse'; + var code = 'ble_mouse.is_connected()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const analog_ble_mouse_input = function (_, generator) { + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var wheel = generator.valueToCode(this, 'wheel', generator.ORDER_ATOMIC); + var re = this.getFieldValue('release'); + generator.definitions_['import_ble_mouse'] = 'from ble_hid_mouse import Mouse'; + var code = "ble_mouse.notify_hid(" + key + ", (" + x + ", " + y + "), " + wheel + ", " + re + ")\n"; + return code; +} + +export const analog_ble_mouse_send_battery = function (_, generator) { + var b = generator.valueToCode(this, 'battery', generator.ORDER_ATOMIC); + generator.definitions_['import_ble_mouse'] = 'from ble_hid_mouse import Mouse'; + var code = "ble_mouse.notify_battery(" + b + ")\n"; + return code; +} + +export const analog_ble_keyboard_mouse_init = function (_, generator) { + generator.definitions_['import_HID_ble_hid'] = 'from ble_hid import HID'; + var kname = generator.valueToCode(this, 'kname', generator.ORDER_ATOMIC) + var code = 'ble_hid = HID(' + kname + ')\n'; + return code; +} + +export const ble_keyboard_mouse_get_mac = function (_, generator) { + generator.definitions_['import_HID_ble_hid'] = 'from ble_hid import HID'; + var code = 'ble_hid.mac'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ble_keyboard_mouse_connect = function (_, generator) { + generator.definitions_['import_HID_ble_hid'] = 'from ble_hid import HID'; + var code = 'ble_hid.is_connected()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const analog_ble_keyboard_mouse_send_battery = function (_, generator) { + var b = generator.valueToCode(this, 'battery', generator.ORDER_ATOMIC); + generator.definitions_['import_HID_ble_hid'] = 'from ble_hid import HID'; + var code = "ble_hid.battery_notify(" + b + ")\n"; + return code; +} + +export const analog_ble_keyboard_mouse_input = function (_, generator) { + var sp = generator.valueToCode(this, 'special', generator.ORDER_ATOMIC); + var ge = generator.valueToCode(this, 'general', generator.ORDER_ATOMIC); + var re = this.getFieldValue('release'); + generator.definitions_['import_HID_ble_hid'] = 'from ble_hid import HID'; + var code = "ble_hid.keyboard_notify(" + sp + ", " + ge + ", " + re + ")\n"; + return code; +} + +export const analog_ble_keyboard_mouse_str = function (_, generator) { + var str = generator.valueToCode(this, 'str', generator.ORDER_ATOMIC); + var t = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + generator.definitions_['import_HID_ble_hid'] = 'from ble_hid import HID'; + var code = "ble_hid.keyboard_str(" + str + ", delay=" + t + ")\n"; + return code; +} + +export const analog_ble_mouse_keyboard_input = function (_, generator) { + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var wheel = generator.valueToCode(this, 'wheel', generator.ORDER_ATOMIC); + var re = this.getFieldValue('release'); + generator.definitions_['import_HID_ble_hid'] = 'from ble_hid import HID'; + var code = "ble_hid.mouse_notify(" + key + ", (" + x + ", " + y + ") ," + wheel + ", " + re + ")\n"; + return code; +} +//educore actuator +export const educore_buzzer = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_speaker'] = 'from ' + version + ' import spesker'; + var code = "speaker()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_buzzer_play_tone = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_speaker'] = 'from ' + version + ' import spesker'; + var bu = generator.valueToCode(this, 'buzzer', generator.ORDER_ATOMIC); + var number_pitch = generator.valueToCode(block, 'pitch', generator.ORDER_ATOMIC); + var code = bu+'.tone(freq=[' + number_pitch + '])\n'; + return code; +} + +export const educore_buzzer_play_tone_time = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_speaker'] = 'from ' + version + ' import spesker'; + var bu = generator.valueToCode(this, 'buzzer', generator.ORDER_ATOMIC); + var number_pitch = generator.valueToCode(block, 'pitch', generator.ORDER_ATOMIC); + var number_time = generator.valueToCode(block, 'time', generator.ORDER_ATOMIC); + var code = bu+'.tone(freq=' + number_pitch + ', dur=' + number_time + ')\n'; + return code; +} + +export const educore_buzzer_stop = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_speaker'] = 'from ' + version + ' import spesker'; + var bu = generator.valueToCode(this, 'buzzer', generator.ORDER_ATOMIC); + var code = bu+'.stop()\n'; + return code; +} + +export const educore_rgb_light = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'rgb'] = 'from ' + version + ' import rgb'; + var code = "rgb()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_neopixel_rgb = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'rgb'] = 'from ' + version + ' import rgb'; + var rgb = generator.valueToCode(this, 'rgb', generator.ORDER_ATOMIC); + var value_led = generator.valueToCode(this, '_LED_', generator.ORDER_ATOMIC); + var value_rvalue = generator.valueToCode(this, 'RVALUE', generator.ORDER_ATOMIC); + var value_gvalue = generator.valueToCode(this, 'GVALUE', generator.ORDER_ATOMIC); + var value_bvalue = generator.valueToCode(this, 'BVALUE', generator.ORDER_ATOMIC); + var code = rgb+'.write(index[' + value_led + '], r=int(' + value_rvalue + '), g=int(' + value_gvalue + '), b=int(' + value_bvalue + '))\n'; + return code; +} + +export const educore_neopixel_clear = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'rgb'] = 'from ' + version + ' import rgb'; + var rgb = generator.valueToCode(this, 'rgb', generator.ORDER_ATOMIC); + var code = rgb+'.clear()\n'; + return code; +} + +export const educore_ble_sensor_init = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_hid'] = 'from ' + version + ' import hid'; + var n = generator.valueToCode(this, 'name', generator.ORDER_ATOMIC); + var code = 'hid.(name='+ n +')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_ble_sensor_connected = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_hid'] = 'from ' + version + ' import hid'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub+'.isconnected()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_ble_keyboard_input = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_keycode'] = 'from ' + version + ' import keycode'; + var ge = generator.valueToCode(this, 'general', generator.ORDER_ATOMIC); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub+".keyboard_send("+ ge + ")\n"; + return code; +} + +export const get_keyboard_light = function (_,generator){ + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var key = this.getFieldValue('key'); + var code = "onboard_bot.hid_keyboard_state()["+ key +']'; + return [code,generator.ORDER_ATOMIC] +} + +export const set_microphone_amplification = function (_,generator){ + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var t = this.getFieldValue('times'); + var code = "onboard_bot.mic_pga("+ t +')\n'; + return code; +} + +export const record_audio = function (_,generator){ + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var str = generator.valueToCode(this, 'str', generator.ORDER_ATOMIC); + var t = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + var code = 'onboard_bot.pcm_record('+str+','+ t +')\n'; + return code; +} + +export const set_music_volume = function (_,generator){ + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_music'] = 'from ' + version + ' import onboard_music'; + var p = generator.valueToCode(this, 'percent', generator.ORDER_ATOMIC); + var code = 'onboard_music.set_volume('+p+')\n'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/ai.js b/mixly/boards/default_src/micropython/generators/ai.js new file mode 100644 index 00000000..c4bb0d41 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/ai.js @@ -0,0 +1,36 @@ +import * as Mixly from 'mixly'; + +export const MICROPYTHON_AI_client = function (_, generator) { + var ctype = this.getFieldValue('CTYPE'); + generator.definitions_['import_baidu_speech'] = 'import baidu_speech'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var api_key = generator.valueToCode(this, 'API_KEY', generator.ORDER_ATOMIC); + var sound = ''; + if (ctype == "ASR") { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_sound'] = "from " + version + " import onboard_sound"; + sound += 'onboard_sound.adc' + ','; + } + var secret_key = generator.valueToCode(this, 'SECRET_KEY', generator.ORDER_ATOMIC); + var code = v + ' = ' + 'baidu_speech.' + ctype + '(' + sound + api_key + ', ' + secret_key + ')\n'; + return code; +} + +export const MICROPYTHON_AI_Speech_unit = function (_, generator) { + generator.definitions_['import_baidu_speech'] = 'import baidu_speech'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var id = generator.valueToCode(this, 'ID', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'STR', generator.ORDER_ATOMIC); + var code = v + '.chatbot(' + id + ',' + s + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const MICROPYTHON_AI_Speech_asr = function (_, generator) { + var language = this.getFieldValue('LANGUAGE'); + generator.definitions_['import_baidu_speech'] = 'import baidu_speech'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var fn = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC) || '""'; + var code = v + '.recognize(record_time=' + fn + ', dev_pid=' + language + ')'; + return [code, generator.ORDER_ATOMIC]; +} + diff --git a/mixly/boards/default_src/micropython/generators/ai_cloud.js b/mixly/boards/default_src/micropython/generators/ai_cloud.js new file mode 100644 index 00000000..4a7b4382 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/ai_cloud.js @@ -0,0 +1,79 @@ +import { Boards } from 'mixly'; + +export const init_xunfei_vi = function (_, generator) { + generator.definitions_['import_mini_xunfei'] = "import mini_xunfei"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var id = generator.valueToCode(this, 'APPID', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'APISecret', generator.ORDER_ATOMIC); + var key = generator.valueToCode(this, 'APIKey', generator.ORDER_ATOMIC); + var code = v + ' = mini_xunfei.ASR_WebSocket(' + id + ',' + key + ',' + s +')\n'; + return code; +} + +export const init_xunfei_Spark_Ultra = function (_, generator) { + generator.definitions_['import_mini_xunfei'] = "import mini_xunfei"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var id = generator.valueToCode(this, 'APPID', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'APISecret', generator.ORDER_ATOMIC); + var key = generator.valueToCode(this, 'APIKey', generator.ORDER_ATOMIC); + var m = this.getFieldValue('model'); + var code = v + ' = mini_xunfei.LLM_WebSocket(' + id + ',' + key + ',' + s + ',"' + m + '")\n'; + return code; +} + +export const init_xunfei_Chinese_Model = function (_, generator) { + generator.definitions_['import_mini_xunfei'] = "import mini_xunfei"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var id = generator.valueToCode(this, 'APPID', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'APISecret', generator.ORDER_ATOMIC); + var key = generator.valueToCode(this, 'APIKey', generator.ORDER_ATOMIC); + var hw = generator.valueToCode(this, 'HW', generator.ORDER_ATOMIC); + var code = v + ' = mini_xunfei.IAT_WebSocket('+id+','+key +','+s+',res_id='+hw+')\n'; + return code; +} + +export const xunfei_vi_run = function (_, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var t = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + var code = v + '.run(' + t +')'; + return [code,generator.ORDER_ATOMIC]; +} + +export const xunfei_Spark_Ultra_run = function (_, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var q = generator.valueToCode(this, 'qus', generator.ORDER_ATOMIC); + var code = v + '.run(' + q +')'; + return [code,generator.ORDER_ATOMIC]; +} + +export const init_xunfei_Spark_Ultra_clr_his = function (_, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = v + '.empty_history()\n'; + return code; +} + +export const llm_set_callback = function (_, generator) { + var v1 = generator.valueToCode(this, "VAR1", generator.ORDER_NONE) || "None"; + var v2 = generator.valueToCode(this, "VAR2", generator.ORDER_NONE) || "None"; + var v3 = generator.valueToCode(this, "VAR3", generator.ORDER_NONE) || "None"; + // var a0 = generator.valueToCode(this, "ADD0", generator.ORDER_NONE) || "None"; + var callback = generator.variableDB_.getName( + generator.valueToCode(this, "callback", generator.ORDER_NONE) || "None", + Blockly.Procedures.NAME_TYPE + ); + var code = new Array(this.itemCount_); + var default_value = "()"; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, generator.ORDER_NONE) || default_value; + } + if (this.itemCount_ > 1){ + var code = v1 +'.function_call(' + callback + ', ' + v2 + ', ' + v3 + ', (' + code.join(', ') +'))\n'; + }else if(this.itemCount_ == 1){ + var code = v1 +'.function_call(' + callback + ', ' + v2 + ', ' + v3 + ', ' + code.join(', ') +')\n'; + }else{ + var code = v1 +'.function_call(' + callback + ', ' + v2 + ', ' + v3 +')\n'; + } + + return code; +} + diff --git a/mixly/boards/default_src/micropython/generators/ai_local.js b/mixly/boards/default_src/micropython/generators/ai_local.js new file mode 100644 index 00000000..39c45775 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/ai_local.js @@ -0,0 +1,642 @@ +import { Boards } from 'mixly'; + + +export const yesorno = function (_, generator) { + var code = this.getFieldValue('state'); + return [code, generator.ORDER_ATOMIC]; +} + +//voice part +export const VOICE_RECOGNITION_CONTROL = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var control = this.getFieldValue('control'); + var code = 'onboard_bot.asr_en(' + control + ')\n'; + return code; +} + +export const CI130X_OPEN_AND_CLOSE = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var status = this.getFieldValue('status'); + if (version == 'mixgo_mini') { + generator.definitions_['import_mini_gx_ext_asr'] = 'from mini_gx import ext_asr'; + var code = 'ext_asr.asr_en(' + status + ')\n'; + } else { + generator.definitions_['import_' + version + '_onboard_asr'] = 'from ' + version + ' import onboard_asr'; + var code = 'onboard_asr.asr_en(' + status + ')\n'; + } + return code; +} + +export const CI130X_IDENTIFY_AND_SAVE_SANT = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_mini') { + generator.definitions_['import_mini_gx_ext_asr'] = 'from mini_gx import ext_asr'; + var code = 'ext_asr.cmd_id()\n'; + } else { + generator.definitions_['import_' + version + '_onboard_asr'] = 'from ' + version + ' import onboard_asr'; + var code = 'onboard_asr.cmd_id()\n'; + } + return code; +} + +export const CI130X_GET_WHETHER_IDENTIFY_SANT = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_mini') { + generator.definitions_['import_mini_gx_ext_asr'] = 'from mini_gx import ext_asr'; + var cmd = this.getFieldValue('cmd'); + var code = 'ext_asr.result(' + cmd + ')'; + } else { + generator.definitions_['import_' + version + '_onboard_asr'] = 'from ' + version + ' import onboard_asr'; + var cmd = this.getFieldValue('cmd'); + var code = 'onboard_asr.result(' + cmd + ')'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const CI130X_GET_THE_RECOGNIZED_CMD_SANT = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_mini') { + generator.definitions_['import_mini_gx_ext_asr'] = 'from mini_gx import ext_asr'; + var key = this.getFieldValue('key'); + if (key == 'status1') { + var code = 'ext_asr.status()[0]'; + } else if (key == 'status2') { + var code = 'ext_asr.status()[1]'; + } else if (key == 'status3') { + var code = 'ext_asr.asr_en()'; + } else { + var code = 'ext_asr.' + key + '()'; + } + } else { + generator.definitions_['import_' + version + '_onboard_asr'] = 'from ' + version + ' import onboard_asr'; + var key = this.getFieldValue('key'); + if (key == 'status1') { + var code = 'onboard_asr.status()[0]'; + } else if (key == 'status2') { + var code = 'onboard_asr.status()[1]'; + } else if (key == 'status3') { + var code = 'ext_asr.asr_en()'; + } else { + var code = 'onboard_asr.' + key + '()'; + } + } + return [code, generator.ORDER_ATOMIC]; +} + +export const CI130X_BROADCAST_SANT = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_mini') { + generator.definitions_['import_mini_gx_ext_asr'] = 'from mini_gx import ext_asr'; + var num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var star = this.getFieldValue('star'); + var end = this.getFieldValue('end'); + var code = 'ext_asr.play(' + star + ', ' + num + ', ' + end + ')\n'; + } else { + generator.definitions_['import_' + version + '_onboard_asr'] = 'from ' + version + ' import onboard_asr'; + var num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var star = this.getFieldValue('star'); + var end = this.getFieldValue('end'); + var code = 'onboard_asr.play(' + star + ', ' + num + ', ' + end + ')\n'; + } + return code; +} + +export const CI130X_SET_SYSTEM_CMD_SANT = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_mini') { + generator.definitions_['import_mini_gx_ext_asr'] = 'from mini_gx import ext_asr'; + var cmd = this.getFieldValue('cmd'); + var code = 'ext_asr.sys_cmd(' + cmd + ')\n'; + } else { + generator.definitions_['import_' + version + '_onboard_asr'] = 'from ' + version + ' import onboard_asr'; + var cmd = this.getFieldValue('cmd'); + var code = 'onboard_asr.sys_cmd(' + cmd + ')\n'; + } + return code; +} + +export const CI130X_BROADCAST_SYSTEM_TIME = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_asr'] = 'from ' + version + ' import onboard_asr'; + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'onboard_asr.play_time(detail=' + bool + ')\n'; + return code; +} + +export const CI130X_PLAY_SYSTEM_CMD_SANT = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_sant') { + generator.definitions_['import_sant_tts'] = 'import sant_tts'; + var text = generator.valueToCode(this, 'text', generator.ORDER_ATOMIC) || '"你们,米思齐"'; + var speed = this.getFieldValue('speed') || '3'; + var code = 'sant_tts.play(' + text + ', speed=' + speed + ')\n'; + } else if (version == 'mixgo_sowl') { + generator.definitions_['import_sant_tts'] = 'import sowl_tts'; + var text = generator.valueToCode(this, 'text', generator.ORDER_ATOMIC) || '"你们,米思齐"'; + var speed = this.getFieldValue('speed') || '3'; + var code = 'sowl_tts.play(' + text + ', speed=' + speed + ')\n'; + } else { + generator.definitions_['import_tts'] = 'import tts'; + var text = generator.valueToCode(this, 'text', generator.ORDER_ATOMIC) || '"你们,米思齐"'; + var speed = this.getFieldValue('speed') || '3'; + var code = 'tts.play(' + text + ', speed=' + speed + ')\n'; + } + return code; +} + +//graph part +export const CREATE_CAMERA = function (_, generator) { + // var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_Camera_FrameSize'] = 'from camera import Camera,FrameSize'; + var cmd = this.getFieldValue('cmd'); + var hm = generator.valueToCode(this, 'HM', generator.ORDER_ATOMIC); + var vf = generator.valueToCode(this, 'VF', generator.ORDER_ATOMIC); + var code = 'camera = Camera(FrameSize.' + cmd + ',hmirror=' + hm + ',vflip=' + vf + ')\n'; + return code; +} + +export const SHOOT_AND_SAVE_PICTURE = function (_, generator) { + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ATOMIC); + var code = 'camera.snapshot(' + direct + ')\n'; + return code; +} + +export const GET_IMAGE_AND_SAVE = function (_, generator) { + generator.definitions_['camera_import_Image'] = 'from camera import Image'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ATOMIC); + var q = generator.valueToCode(this, 'quality', generator.ORDER_ATOMIC); + var a = this.getFieldValue('angle'); + var code = 'Image.save(' + sub + ',path=' + direct + ',quality=' + q + ',rotation=' + a + ')\n'; + return code; +} + +export const OPEN_IMAGE = function (_, generator) { + generator.definitions_['camera_import_Image'] = 'from camera import Image'; + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ATOMIC); + var a = this.getFieldValue('angle'); + var w = generator.valueToCode(this, 'w', generator.ORDER_ATOMIC); + var h = generator.valueToCode(this, 'h', generator.ORDER_ATOMIC); + var code = 'Image.open(path=' + direct + ',rotation=' + a + ',scale_width=' + w + ',scale_height=' + h + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_IMAGE_FROM_NET = function (_, generator) { + generator.definitions_['camera_import_Image'] = 'from camera import Image'; + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ATOMIC); + var a = this.getFieldValue('angle'); + var w = generator.valueToCode(this, 'w', generator.ORDER_ATOMIC); + var h = generator.valueToCode(this, 'h', generator.ORDER_ATOMIC); + var code = 'Image.download(url=' + direct + ', rotation=' + a + ', scale_width=' + w + ', scale_height=' + h + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const CAMERA_LOOGOUT = function () { + var code = 'camera.deinit()\n'; + return code; +} + +export const GET_PICTURE_DATA_EXACT = function (_, generator) { + // var kind = this.getFieldValue('kind'); + var code = 'camera.capture()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_PICTURE_WIDTH_HEIGHT_DEVICE = function (_, generator) { + var kind = this.getFieldValue('kind'); + var code = 'camera.' + kind + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const CONVERT_IMAGE_TO_JPG = function (_, generator) { + generator.definitions_['camera_import_Image'] = 'from camera import Image'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var kind = this.getFieldValue('kind'); + var q = generator.valueToCode(this, 'quality', generator.ORDER_ATOMIC); + var code = 'Image.convert(' + sub + ', formats=' + kind + ', quality=' + q + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_PICTURE_DATA_WHS = function (_, generator) { + generator.definitions_['camera_import_Image'] = 'from camera import Image'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var kind = this.getFieldValue('kind'); + var code = sub + '.' + kind; + return [code, generator.ORDER_ATOMIC]; +} + +export const SCREEN_SHOW_CAM_GRAPH_SHOOT = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'onboard_tft.display(' + sub + ', sync=' + bool + ')\n'; + return code; +} + +export const SCREEN_SHOW_CAM_GRAPH_SHOOT_LOCATION = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'onboard_tft.display(' + sub + ',x=' + x + ',y=' + y + ', sync=' + bool + ')\n'; + return code; +} + +export const SCREEN_DISPLAY_IMAGE = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ATOMIC); + var a = this.getFieldValue('angle'); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'onboard_tft.display(' + direct + ',rotation=' + a + ',sync=' + bool + ')\n'; + return code; +} + +export const SCREEN_DISPLAY_IMAGE_LOCATION = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var a = this.getFieldValue('angle'); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'onboard_tft.display(' + direct + ',x=' + x + ',y=' + y + ',rotation=' + a + ',sync=' + bool + ')\n'; + return code; +} + +export const GET_SCREEN_IMAGE = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var code = 'onboard_tft.screenshot()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_SCREEN_IMAGE_SIZE = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var w = generator.valueToCode(this, 'w', generator.ORDER_ATOMIC); + var h = generator.valueToCode(this, 'h', generator.ORDER_ATOMIC); + var code = 'onboard_tft.screenshot(x=' + x + ',y=' + y + ',w=' + w + ',h=' + h + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const AI_CAMERA_INIT = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var cmd = this.getFieldValue('kind'); + var width = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC); + var height = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC); + var code = sub + ' = esp_dl.' + cmd + '(width=' + width + ', height=' + height + ')\n'; + return code; +} + +export const MODEL_INIT_WIDTH = function (_, generator) { + var width = this.getFieldValue('width'); + var code = width; + return [code, generator.ORDER_ATOMIC]; +} + +export const MODEL_INIT_HEIGHT = function (_, generator) { + var height = this.getFieldValue('height'); + var code = height; + return [code, generator.ORDER_ATOMIC]; +} + +export const AI_CAMERA_INIT_FACERECOGNIZE = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var path = generator.valueToCode(this, 'PATH', generator.ORDER_ATOMIC); + var width = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC); + var height = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC); + var code = sub + ' = esp_dl.FaceRecognizer(width=' + width + ', height=' + height + ', db_path=' + path + ')\n'; + return code; +} + +export const MODEL_LOGOUT = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = 'del ' + sub + '\n'; + return code; +} + +export const MODEL_RUN = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var frame = generator.valueToCode(this, 'FRAME', generator.ORDER_ATOMIC); + var code = sub + '.run(' + frame + '.image)'; + return [code, generator.ORDER_ATOMIC]; +} + +export const MODEL_WHETHER_RUN_SUCCEED = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + + var code = 'esp_dl.analyze(' + sub + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_HOW_MUCH_RECOGNITION = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = 'esp_dl.analyze(' + sub + ',"len")'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_NO_RECOGNITION = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var no = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + var code = 'esp_dl.analyze(' + sub + ',"data",' + no + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_NO_XY_RECOGNITION = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var no = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + var coord = this.getFieldValue('coord'); + if (coord == "all") { + var code = 'esp_dl.analyze(' + sub + ',"box",' + no + ')'; + } else { + var code = 'esp_dl.analyze(' + sub + ',"box",' + no + ')[' + coord + ']'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_NO_XY_RECOGNITION_FACE = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var no = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + var part = this.getFieldValue('part'); + if (part == "all") { + var code = 'esp_dl.analyze(' + sub + ',"features",' + no + ')'; + } else { + var code = 'esp_dl.analyze(' + sub + ',"features",' + no + ')' + part; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_NO_CAT_OR_FACE_RECOGNITION = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var no = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + var code = 'esp_dl.analyze(' + sub + ',"score",' + no + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const Register_color_recognition_fixed = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var color = this.getFieldValue('color'); + var area = generator.valueToCode(this, 'AREA', generator.ORDER_ATOMIC); + if (color == "red") { + var code = sub + '.register_color((170, 100, 100), (10, 255, 255),"' + color + '", ' + area + ')\n'; + } else if (color == "green") { + var code = sub + '.register_color((35, 100, 100), (85, 255, 255),"' + color + '",' + area + ')\n'; + } else if (color == "blue") { + var code = sub + '.register_color((100, 100, 100), (130, 255, 255),"' + color + '", ' + area + ')\n'; + } else if (color == "yellow") { + var code = sub + '.register_color((20, 100, 100), (35, 255, 255),"' + color + '", ' + area + ')\n'; + } else if (color == "cyan") { + var code = sub + '.register_color((85, 100, 100), (100, 255, 255),"' + color + '", ' + area + ')\n'; + } else if (color == "purple") { + var code = sub + '.register_color((130, 100, 100), (150, 255, 255),"' + color + '", ' + area + ')\n'; + } else if (color == "black") { + var code = sub + '.register_color((0, 0, 0), (180, 255, 50),"' + color + '", ' + area + ')\n'; + } else if (color == "white") { + var code = sub + '.register_color((0, 0, 200), (180, 50, 255),"' + color + '", ' + area + ')\n'; + } + return code; +} + +export const Register_color_recognition = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var min = generator.valueToCode(this, 'MIN', generator.ORDER_ATOMIC); + var max = generator.valueToCode(this, 'MAX', generator.ORDER_ATOMIC); + var color = generator.valueToCode(this, 'COLOR', generator.ORDER_ATOMIC); + var area = generator.valueToCode(this, 'AREA', generator.ORDER_ATOMIC); + var code = sub + '.register_color(' + min + ', ' + max + ', ' + color + ', ' + area + ')\n'; + return code; +} + +export const REGISTER_NEW_FACE = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var image = generator.valueToCode(this, 'IMAGE', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'NAME', generator.ORDER_ATOMIC); + var code = sub + '.enroll(' + image + '.image, name=' + name + ', validate = 1)'; + return [code, generator.ORDER_ATOMIC]; +} + +export const DELETE_FACE_FROM_DATABASE = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var id = generator.valueToCode(this, 'ID', generator.ORDER_ATOMIC); + var code = sub + '.delete_face(' + id + ')\n'; + return code; +} + +export const DELETE_FACE_ALL = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.clear_face()\n'; + return code; +} + +export const PRINT_FACE_DATABASE = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.print_database()\n'; + return code; +} + +export const GET_QR_CODE_RECOGNITION_DATA = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'esp_dl.simple_run(' + sub + ', camera, "data", color=0xF800, sync=' + bool + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_PICTURE_RECOGNITION_DATA = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'esp_dl.simple_run(' + sub + ', camera, "data", color=0xF800, sync=' + bool + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_COLOR_DETECTION_NUM = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'esp_dl.simple_run(' + sub + ', camera, "len", color=0xF800, sync=' + bool + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +// export const GET_COLOR_DETECTION_LOCATION = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var num = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); +// var color = this.getFieldValue('color'); +// var code = sub + '.color_detection('+ color +",'pos',"+ num +')'; +// return [code, generator.ORDER_ATOMIC]; +// } + +export const GET_CAT_FACE_DETECTION_NUM = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'esp_dl.simple_run(' + sub + ', camera, "len", color=0xF800, sync=' + bool + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +// export const GET_CAT_FACE_DETECTION_LOCATION = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var num = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); +// var code = sub + ".cat_detection('pos',"+ num +')'; +// return [code, generator.ORDER_ATOMIC]; +// } + +export const GET_HUMAN_DETECTION_NUM = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'esp_dl.simple_run(' + sub + ', camera, "len", color=0xF800, sync=' + bool + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_FACE_DETECTION_NUM = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'esp_dl.simple_run(' + sub + ', camera, "len", color=0xF800, sync=' + bool + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const GET_FACE_DETECTION_NAME = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl' + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bool = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC); + var code = 'esp_dl.simple_run(' + sub + ', camera, "person", "name", color=0xF800, sync=' + bool + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +// export const GET_FACE_DETECTION_LOCATION = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var num = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); +// var code = sub + ".face_detection('pos',"+ num +')'; +// return [code, generator.ORDER_ATOMIC]; +// } + +// export const GET_FACE_DETECTION_KEYPOINT_LOCATION = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var num = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); +// var kp = this.getFieldValue('kp'); +// var code = sub + ".face_detection('keypoint',"+ num +','+ kp +')'; +// return [code, generator.ORDER_ATOMIC]; +// } + +// export const GET_FACE_RECOGNITION_ID = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var code = sub + ".face_recognition('len')"; +// return [code, generator.ORDER_ATOMIC]; +// } + +// export const GET_FACE_RECOGNITION_ID_LOCATION = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var num = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); +// var code = sub + ".face_recognition('pos',"+ num +')'; +// return [code, generator.ORDER_ATOMIC]; +// } + +// export const GET_FACE_RECOGNITION_ID_KEYPOINT_LOCATION = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var num = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); +// var kp = this.getFieldValue('kp'); +// var code = sub + ".face_recognition('keypoint',"+ num +','+ kp +')'; +// return [code, generator.ORDER_ATOMIC]; +// } + +export const GET_NO_FACE_RECOGNITION_INFO = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + var kind = this.getFieldValue('kind'); + var code = "esp_dl.analyze(" + sub + ', "person",' + num + ')["' + kind + '"]'; + return [code, generator.ORDER_ATOMIC]; +} + +// export const PEOPLE_FACE_ENROLL = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var code = sub + '.face_enroll()'; +// return [code, generator.ORDER_ATOMIC]; +// } + +// export const DELETE_PEOPLE_FACE_ID = function (_, generator) { +// var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); +// var id = generator.valueToCode(this, 'ID', generator.ORDER_ATOMIC); +// var code = sub + '.face_delete('+ id +')\n'; +// return code; +// } + +export const AI_STOP_ACQUISITION = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.stop()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const MIXIO_REPORT_IMAGE_DATA = function (_, generator) { + generator.definitions_['import_base64'] = 'import base64'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = 'mixiot.image_base64(' + sub + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +//simplified part +export const CREATE_CAMERA_SIMPLE = function (_, generator) { + generator.definitions_['import_Camera_FrameSize'] = 'from camera import Camera,FrameSize'; + var cmd = this.getFieldValue('cmd'); + var code = 'camera = Camera(FrameSize.' + cmd + ', hmirror=False,vflip=False)\n'; + return code; +} + +export const AI_CAMERA_INIT_SIMPLE = function (_, generator) { + generator.definitions_['import_esp_dl'] = 'import esp_dl'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var cmd = this.getFieldValue('kind'); + if (cmd == "FaceRecognizer") { + var code = sub + ' = esp_dl.' + cmd + '(width=camera.get_pixel_width(), height=camera.get_pixel_height() , db_path="face.db")\n'; + } else { + var code = sub + ' = esp_dl.' + cmd + '(width=camera.get_pixel_width(), height=camera.get_pixel_height())\n'; + } + return code; +} + +export const Register_color_recognition_fixed_SIMPLE = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var color = this.getFieldValue('color'); + if (color == "red") { + var code = sub + '.register_color((170, 100, 100), (10, 255, 255),"' + color + '")\n'; + } else if (color == "green") { + var code = sub + '.register_color((35, 100, 100), (85, 255, 255),"' + color + '")\n'; + } else if (color == "blue") { + var code = sub + '.register_color((100, 100, 100), (130, 255, 255),"' + color + '")\n'; + } else if (color == "yellow") { + var code = sub + '.register_color((20, 100, 100), (35, 255, 255),"' + color + '")\n'; + } else if (color == "cyan") { + var code = sub + '.register_color((85, 100, 100), (100, 255, 255),"' + color + '")\n'; + } else if (color == "purple") { + var code = sub + '.register_color((130, 100, 100), (150, 255, 255),"' + color + '")\n'; + } else if (color == "black") { + var code = sub + '.register_color((0, 0, 0), (180, 255, 50),"' + color + '")\n'; + } else if (color == "white") { + var code = sub + '.register_color((0, 0, 200), (180, 50, 255),"' + color + '")\n'; + } + return code; +} + +export const REGISTER_NEW_FACE_SIMPLE = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'NAME', generator.ORDER_ATOMIC); + var code = sub + '.enroll(camera.capture().image, name=' + name + ', validate = 1)'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/ai_sensor.js b/mixly/boards/default_src/micropython/generators/ai_sensor.js new file mode 100644 index 00000000..472837e5 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/ai_sensor.js @@ -0,0 +1,283 @@ +export const ai_sensor_use_uart_init = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = v + '=mixgo_ai.AI(' + key + ', quick=1)\n'; + return code; +} + +export const ai_sensor_qrcode_lite = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var type = this.getFieldValue('TYPE'); + var code = sub + '.find_' + type + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_config = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var rx = generator.valueToCode(this, 'RX', generator.ORDER_ATOMIC); + var tx = generator.valueToCode(this, 'TX', generator.ORDER_ATOMIC); + var dropdown_uart = this.getFieldValue('mode'); + var code = v + '.configure(' + tx + ', ' + rx + ', restart=' + dropdown_uart + ')\n'; + return code; +} + +export const ai_sensor_rgb = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var led1 = generator.valueToCode(this, 'led1', generator.ORDER_ATOMIC); + var led2 = generator.valueToCode(this, 'led2', generator.ORDER_ATOMIC); + var code = v + '.led_rgb(' + led1 + ', ' + led2 + ')\n'; + return code; +} + +export const ai_sensor_qrcode = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_qrcodes = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.find_qrcodes()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_barcode = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_barcodes = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.find_barcodes()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_tag = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_tags = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.find_apriltags()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_line = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_lines = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var v3 = generator.valueToCode(this, 'VAR3', generator.ORDER_ATOMIC); + var code = v + '.find_lines(' + v1 + ', ' + v2 + ', ' + v3 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_circle = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_circles = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var v3 = generator.valueToCode(this, 'VAR3', generator.ORDER_ATOMIC); + var code = v + '.find_circles(' + v1 + ', ' + v2 + ', ' + v3 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_rect = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_rects = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var code = v + '.find_rects(' + v1 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_color = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_colors = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.find_colors()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_color_chases_result = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_color_chases = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var v3 = generator.valueToCode(this, 'VAR3', generator.ORDER_ATOMIC); + var code = v + '.color_track(' + v1 + ', ' + v2 + ', ' + v3 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_ailocal_train = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var v3 = generator.valueToCode(this, 'VAR3', generator.ORDER_ATOMIC); + var v4 = generator.valueToCode(this, 'VAR4', generator.ORDER_ATOMIC); + var code = v + '.ailocal_train(' + v1 + ', ' + v2 + ', ' + v3 + ', ' + v4 + ')\n'; + return code; +} + +export const ai_sensor_ailocal_class = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var v4 = generator.valueToCode(this, 'VAR4', generator.ORDER_ATOMIC); + var code = v + '.ailocal_class(' + v1 + ', ' + v2 + ', ' + v4 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_ailocal_class_result = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_audio_record = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var code = v + '.audio_record(path=' + v1 + ', times=' + v2 + ')\n'; + return code; +} + +export const ai_sensor_audio_play = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var code = v + '.audio_play(path=' + v1 + ', volume=' + v2 + ')\n'; + return code; +} + +export const ai_sensor_yolo_recognize = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var v4 = generator.valueToCode(this, 'VAR4', generator.ORDER_ATOMIC); + var code = v + '.yolo_recognize(' + v1 + ', ' + v2 + ', ' + v4 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_yolo_recognize_result = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_asr_recognize = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v1 = generator.valueToCode(this, 'VAR1', generator.ORDER_ATOMIC); + var v2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var code = v + '.asr_recognize(' + v1 + ', threshold=' + v2 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_licenseplate = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_licenseplates = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.find_licenseplate()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_face = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_classifier_faces = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.face_detect()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_20object = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var sub = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const ai_sensor_find_20objects = function (_, generator) { + generator.definitions_['import_mixgo_ai'] = 'import mixgo_ai'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.find_20object()'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/blynk.js b/mixly/boards/default_src/micropython/generators/blynk.js new file mode 100644 index 00000000..2ca5855f --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/blynk.js @@ -0,0 +1,222 @@ +// Blynk 第二版 +// Blynk 自定义终端部件 Terminal +export const mpython_blynk_terminal_widget_vpin = function (_, generator) { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + var virtual_pin = generator.valueToCode(this, 'virtual_pin', generator.ORDER_ATOMIC); + + generator.functions_['terminal_widget_vpin_' + virtual_pin] = + ` +ALLOWED_COMMANDS_LIST = ['ls', 'lsusb', 'ip a', 'ip abc'] + +@blynk.handle_event('write V${virtual_pin}') +def write_handler(pin, _values): + header = '' + result = '' + delimiter = '{}\\n'.format('=' * 30) + if _values and _values[0] in ALLOWED_COMMANDS_LIST: + cmd_params = _values[0].split(' ') + try: + result = subprocess.check_output(cmd_params).decode('utf-8') + header = '[output]\\n' + except subprocess.CalledProcessError as exe_err: + header = '[error]\\n' + result = 'Return Code: {}\\n'.format(exe_err.returncode) + except Exception as g_err: + print("Command caused '{}'".format(g_err)) + elif _values and _values[0] == 'help': + header = '[help -> allowed commands]\\n' + result = '{}\\n'.format('\\n'.join(ALLOWED_COMMANDS_LIST)) + + # communicate with terminal if help or some allowed command + if result: + output = '{}{}{}{}'.format(header, delimiter, result, delimiter) + print(output) + blynk.virtual_write(pin, output) + blynk.virtual_write(pin, '\\n') +` + + var code = ''; + return code; +} + +// Blynk 同步虚拟管脚的状态 +export const mpython_blynk_sync_virtual = function (_, generator) { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + var virtual_pin = generator.valueToCode(this, 'virtual_pin', generator.ORDER_ATOMIC); + + var code = 'blynk.virtual_sync(' + virtual_pin + ')\n'; + return code; +} + +// 斷開连接 Blynk +export const mpython_blynk_on_disconnected = function (_, generator) { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + + var branch = generator.statementToCode(this, 'DO'); + branch = generator.addLoopTrap(branch, this.id) || generator.PASS; + + generator.definitions_['blynk_on_disconnected'] = + '@blynk.handle_event("disconnect")\n' + + 'def connect_handler():\n' + + " print('Blynk disconnected')\n" + branch; + + return ''; +} + +// 连接上 Blynk +export const mpython_blynk_on_connected = function (_, generator) { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + + var branch = generator.statementToCode(this, 'DO'); + branch = generator.addLoopTrap(branch, this.id) || generator.PASS; + + generator.definitions_['blynk_on_connected'] = + '@blynk.handle_event("connect")\n' + + 'def connect_handler():\n' + + " print('Blynk connected')\n" + branch; + + return ''; +} + +// Blynk 定时器的进程生效并运行 +export const mpython_blynktimer_run = function () { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + // generator.definitions_['import_blynktimer'] = 'import blynktimer'; + + var code = 'blynk_timer.run()\n'; + return code; +} + +// Blynk 进程生效并运行 +export const mpython_blynk_run = function () { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + + var code = 'blynk.run()\n'; + return code; +} + +// Blynk APP 显示通知 +export const mpython_blynk_app_notify = function (_, generator) { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + var notification = generator.valueToCode(this, 'notification', generator.ORDER_ATOMIC); + + var code = 'blynk.notify(' + notification + ')\n'; + return code; +} + +// 停止 Blynk 定时器 %1 +export const mpython_blynk_stop_timers = function (_, generator) { + generator.definitions_['import_blynktimer'] = 'import blynktimer'; + generator.definitions_['def_blynktimer'] = 'blynk_timer = blynktimer.Timer(no_timers_err=False)'; + + var timer_num = generator.valueToCode(this, 'timer_num', generator.ORDER_ATOMIC); + var code = `blynk_timer.stop('${timer_num}_blynk_timer${timer_num}')` + '\n'; + + return code; +} + +// 可用的 Blynk 定时器 +export const mpython_blynk_get_timers = function (_, generator) { + generator.definitions_['import_blynktimer'] = 'import blynktimer'; + generator.definitions_['def_blynktimer'] = 'blynk_timer = blynktimer.Timer(no_timers_err=False)'; + + var code = `blynk_timer.get_timers()`; + return [code, generator.ORDER_ATOMIC]; +} + +//blynk定时器 +export const mpython_blynktimer = function (_, generator) { + generator.definitions_['import_blynktimer'] = 'import blynktimer'; + + var Num = generator.valueToCode(this, 'Num', generator.ORDER_ATOMIC); + var period = generator.valueToCode(this, 'period', generator.ORDER_ATOMIC); + var Timer_mode = this.getFieldValue('Timer_mode'); + + var branch = generator.statementToCode(this, 'DO'); + branch = generator.addLoopTrap(branch, this.id) || generator.PASS; + + generator.definitions_['def_blynktimer'] = 'blynk_timer = blynktimer.Timer(no_timers_err=False)'; + + generator.definitions_['blynktimer_event' + Num] = + ` +@blynk_timer.register(interval=${period}, run_once=${Timer_mode}) +def blynk_timer${Num}(): +` + + branch; + return ''; +} + +// 发送数据 %1 到 Bylnk APP 的虚拟管脚 %2 +export const mpython_blynk_sensor_data_to_app = function (_, generator) { + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + var sensor_data = generator.valueToCode(this, 'sensor_data', generator.ORDER_ATOMIC); + var virtual_pin = generator.valueToCode(this, 'virtual_pin', generator.ORDER_ATOMIC); + var code = 'blynk.virtual_write(' + virtual_pin + ', ' + sensor_data + ')\n'; + return code; +} + +// 从 Bylnk APP 获取虚拟管脚 %1 的值 +export const mpython_blynk_app_data = function (_, generator) { + + // generator.definitions_['import_BlynkLib'] = 'import blynklib'; + var virtual_pin = generator.valueToCode(this, 'virtual_pin', generator.ORDER_ATOMIC); + + var branch = generator.statementToCode(this, 'DO'); + branch = generator.addLoopTrap(branch, this.id) || generator.PASS; + + generator.definitions_['blynk_VIRTUAL_WRITE_' + virtual_pin] = + "@blynk.handle_event('write V" + virtual_pin + "')\n" + + 'def write_virtual_pin_handler(pin, _value):\n' + + ' for i in range(0, len(_value)):\n' + + ' try: _value[i] = eval(_value[i])\n' + + ' except: pass\n' + + ' if len(_value) == 1: _value = _value[0]\n' + branch; + //' print('+'"v' + virtual_pin + '_value: {}".format(_value))\n' + // var code = 'blynk.run()\n'; + return ''; +} + +// 向 %1 发邮件 主题 %2 正文 %3 +export const mpython_blynk_email = function (_, generator) { + var body = generator.valueToCode(this, 'body', generator.ORDER_ATOMIC); + var subject = generator.valueToCode(this, 'subject', generator.ORDER_ATOMIC); + var TargetEmail = generator.valueToCode(this, 'TargetEmail', generator.ORDER_ATOMIC); + + var code = `blynk.email(${TargetEmail}, ${subject}, ${body})` + '\n'; + return code; +} + +// 给虚拟管脚添加 属性 %1 值 %2 +export const mpython_blynk_set_property = function (_, generator) { + var attribute_value = generator.valueToCode(this, 'attribute_value', generator.ORDER_ATOMIC); + var attribute_name = generator.valueToCode(this, 'attribute_name', generator.ORDER_ATOMIC); + var code = `blynk.set_property(pin, ${attribute_name}, ${attribute_value})` + '\n'; + return code; +} + +// Bylnk设置 +export const mpython_blynk_setup = function (_, generator) { + generator.definitions_['import_BlynkLib'] = 'import blynklib'; + var server = generator.valueToCode(this, 'server', generator.ORDER_ATOMIC); + var auth = generator.valueToCode(this, 'auth', generator.ORDER_ATOMIC); + var port = generator.valueToCode(this, 'port', generator.ORDER_ATOMIC); + + generator.definitions_['mpython_blynk_setup'] = + "blynk = blynklib.Blynk(" + auth + ", server=" + server + ", port=" + port + ")"; + + generator.definitions_['blynk_on_connected'] = + ` +@blynk.handle_event("connect") +def connect_handler(): + print('Blynk connected') +` + + generator.definitions_['blynk_on_disconnected'] = + ` +@blynk.handle_event("disconnect") +def connect_handler(): + print('Blynk disconnected') +` + + return ''; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/cc_g1.js b/mixly/boards/default_src/micropython/generators/cc_g1.js new file mode 100644 index 00000000..758ec88b --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/cc_g1.js @@ -0,0 +1,25 @@ +export const cc_g1_read_bat = function (_, generator) { + generator.definitions_['import_cc_g1'] = 'from cc_g1 import handle'; + var code = 'handle.read_bat()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const cc_g1_read_joystick = function (_, generator) { + var v = this.getFieldValue('VAR'); + generator.definitions_['import_cc_g1'] = 'from cc_g1 import handle'; + var code = 'handle.read_joystick()' + v + ''; + return [code, generator.ORDER_ATOMIC]; +} + +export const cc_g1_read_key = function (_, generator) { + var v = this.getFieldValue('VAR'); + generator.definitions_['import_cc_g1'] = 'from cc_g1 import handle'; + var code = 'handle.read_key(' + v + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const cc_g1_turnoff = function (_, generator) { + generator.definitions_['import_cc_g1'] = 'from cc_g1 import handle'; + var code = 'handle.shutdown()'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/ce_go.js b/mixly/boards/default_src/micropython/generators/ce_go.js new file mode 100644 index 00000000..479ee626 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/ce_go.js @@ -0,0 +1,286 @@ +import * as Mixly from 'mixly'; + +export const ce_go_light_number = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } + var code = 'car.' + this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const ce_go_led_bright = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var bright = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = "car.setonoff(" + op + ", " + bright + ")\n"; + return code; +} + +export const ce_go_get_led_bright = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var code = "car.getrightness(" + op + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const ce_go_get_led_state = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var code = "car.getonoff(" + op + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const ce_go_led_brightness = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } + var op = generator.valueToCode(this, 'led', generator.ORDER_ATOMIC); + var flag = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + var code = "car.setbrightness(" + op + ", " + flag + ")\n"; + return code; +} + +export const ce_go_stepper_keep = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } + var v = this.getFieldValue('VAR'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT); + var code = 'car.move("' + v + '", ' + speed + ")\n"; + return code; +} + +export const ce_go_stepper_stop = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } + var v = this.getFieldValue('VAR'); + var code = 'car.move("' + v + '")\n'; + return code; +} + +export const ce_go_dc_motor = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_car'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_car'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_car'] = 'from mini_go import car'; + } + var wheel = this.getFieldValue('wheel'); + var v = this.getFieldValue('direction'); + if (wheel == 0) { + if (v == 'CW') { v = 'CCW' } + else if (v == 'CCW') { v = 'CW' } + } + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = "car.motor(car.MOTO[" + wheel + '], "' + v + '", ' + speed + ")\n"; + return code; +} + +export const ce_go_hall_attachInterrupt = function (_, generator) { + var dropdown_mode = this.getFieldValue('mode'); + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_hall_' + dropdown_mode] = 'from me_go import hall_' + dropdown_mode; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_hall_' + dropdown_mode] = 'from ce_go import hall_' + dropdown_mode; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_hall' + dropdown_mode] = 'from mini_go import hall_' + dropdown_mode; + } + var atta = generator.valueToCode(this, 'DO', generator.ORDER_ATOMIC); + var code = 'hall_' + dropdown_mode + '.irq_cb(' + atta + ')\n' + return code; +} + +export const ce_go_hall_initialize = function (_, generator) { + var dropdown_mode = this.getFieldValue('mode'); + var args = this.getFieldValue('args'); + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_hall_' + dropdown_mode] = 'from me_go import hall_' + dropdown_mode; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_hall_' + dropdown_mode] = 'from ce_go import hall_' + dropdown_mode; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_hall' + dropdown_mode] = 'from mini_go import hall_' + dropdown_mode; + } + var num = generator.valueToCode(this, 'num', generator.ORDER_ATOMIC); + if (args == 'all') { + var code = 'hall_' + dropdown_mode + '.initial(' + 'turns' + '=' + num + ', distance=' + num + ')\n' + return code; + } + var code = 'hall_' + dropdown_mode + '.initial(' + args + '=' + num + ')\n' + return code; +} + +export const ce_go_hall_data = function (_, generator) { + var dropdown_mode = this.getFieldValue('mode'); + var args = this.getFieldValue('args'); + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_hall_' + dropdown_mode] = 'from me_go import hall_' + dropdown_mode; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_hall_' + dropdown_mode] = 'from ce_go import hall_' + dropdown_mode; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_hall' + dropdown_mode] = 'from mini_go import hall_' + dropdown_mode; + } + var code = 'hall_' + dropdown_mode + '.' + args + ''; + return [code, generator.ORDER_ATOMIC]; +} + +export const ce_go_pin_near_line = function (_, generator) { + var key = this.getFieldValue('key'); + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_hall'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_hall'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_hall'] = 'from mini_go import car'; + } + var code = 'car.patrol()' + key + ''; + return [code, generator.ORDER_ATOMIC]; +} + +export const ce_go_pin_near = function (_, generator) { + var key = this.getFieldValue('key'); + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_hall'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_hall'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_hall'] = 'from mini_go import car'; + } + var code = 'car.obstacle()' + key + ''; + return [code, generator.ORDER_ATOMIC]; +} + +export const ce_go_pin_near_state_change = function (_, generator) { + var key = this.getFieldValue('key'); + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_hall'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_hall'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_hall'] = 'from mini_go import car'; + } + var code = 'car.ir_mode(car.' + key + ')\n'; + return code; +} + +export const sensor_mixgome_eulerangles = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_mixgo_me_onboard_mxc6655xa'] = "from mixgo_me import onboard_mxc6655xa"; + } else if (version == "mixgo_ce") { + generator.definitions_['import_mixgo_ce_onboard_mxc6655xa'] = "from mixgo_ce import onboard_mxc6655xa"; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_onboard_mxc6655xa'] = 'from mini_go import onboard_mxc6655xa'; + } + var angle = this.getFieldValue('angle'); + var code = 'onboard_mxc6655xa.eulerangles(upright=True)' + angle; + return [code, generator.ORDER_ATOMIC]; +} + +export const ce_go_pin_light = function (_, generator) { + var key = this.getFieldValue('key'); + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + if (version == "mixgo_me" || version == "mixgo_cc") { + generator.definitions_['import_me_go_hall'] = 'from me_go import car'; + } else if (version == "mixgo_ce") { + generator.definitions_['import_ce_go_hall'] = 'from ce_go import car'; + } else if (version == "mixgo_mini") { + generator.definitions_['import_mini_go_hall'] = 'from mini_go import car'; + } + var code = 'car.light()' + key + ''; + return [code, generator.ORDER_ATOMIC]; +} + +//educore car + +export const educore_car = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_car'] = 'from ' + version + ' import car'; + var code = 'car()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_car_stepper_keep = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_car'] = 'from ' + version + ' import car'; + var car = generator.valueToCode(this, 'car', generator.ORDER_ASSIGNMENT); + var v = this.getFieldValue('VAR'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ASSIGNMENT); + var code = car + '.' + v + '(' + speed + ")\n"; + return code; +} + +export const educore_car_stepper_stop = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_car'] = 'from ' + version + ' import car'; + var car = generator.valueToCode(this, 'car', generator.ORDER_ASSIGNMENT); + var v = this.getFieldValue('VAR'); + var code = car + '.' + v + "()\n"; + return code; +} + +export const educore_car_pin_near_line = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_car'] = 'from ' + version + ' import car'; + var car = generator.valueToCode(this, 'car', generator.ORDER_ASSIGNMENT); + var key = this.getFieldValue('key'); + var code = car + '.get_itr_dnum(' + key + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_car_pin_near = function (_, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_car'] = 'from ' + version + ' import car'; + var car = generator.valueToCode(this, 'car', generator.ORDER_ASSIGNMENT); + var code = car + '.get_distance()'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/communicate.js b/mixly/boards/default_src/micropython/generators/communicate.js new file mode 100644 index 00000000..86f558d8 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/communicate.js @@ -0,0 +1,613 @@ +import * as Blockly from 'blockly/core'; +import * as Mixly from 'mixly'; + +export const communicate_i2c_onboard = function (block, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_i2c'] = 'from ' + version + ' import onboard_i2c'; + var code = 'onboard_i2c'; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_spi_onboard = function (block, generator) { + var version = Mixly.Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_i2c'] = 'from ' + version + ' import onboard_spi'; + var code = 'onboard_spi'; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_i2c_init = function (block, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin1 = generator.valueToCode(this, 'RX', generator.ORDER_ATOMIC); + var dropdown_pin2 = generator.valueToCode(this, 'TX', generator.ORDER_ATOMIC); + var freq = generator.valueToCode(this, 'freq', generator.ORDER_ATOMIC); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + return "" + sub + " = machine.SoftI2C(scl = machine.Pin(" + dropdown_pin2 + "), sda=machine.Pin(" + dropdown_pin1 + "), freq=" + freq + ")\n"; +} + +export const communicate_i2c_read = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var address = generator.valueToCode(this, 'address', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + return ["" + name + ".readfrom(" + address + ", " + data + ")", generator.ORDER_ATOMIC]; +} + +export const communicate_i2c_write = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var address = generator.valueToCode(this, 'address', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + return "" + name + ".writeto(" + address + ", " + data + ")\n"; +} + +export const communicate_i2c_scan = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return ["" + name + ".scan()", generator.ORDER_ATOMIC]; +} + +export const communicate_i2c_master_read = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + name + ".read()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_i2c_available = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + name + ".available()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const i2c_slave_onreceive = function (block, generator) { + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + generator.setups_['setup_i2c_' + pin] = 'Wire.begin(' + pin + ');'; + generator.setups_['setup_i2c_onReceive_' + pin] = 'Wire.onReceive(i2cReceiveEvent_' + pin + ');'; + var funcName = 'i2cReceiveEvent_' + pin; + var branch = generator.statementToCode(this, 'DO'); + var code2 = 'void' + ' ' + funcName + '(int howMany) {\n' + branch + '}\n'; + generator.definitions_[funcName] = code2; + return ''; +} + +export const communicate_spi_init = function (block, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var freq = generator.valueToCode(this, 'freq', generator.ORDER_ATOMIC); + var mosi = generator.valueToCode(this, 'mosi', generator.ORDER_ATOMIC); + var miso = generator.valueToCode(this, 'miso', generator.ORDER_ATOMIC); + var sck = generator.valueToCode(this, 'sck', generator.ORDER_ATOMIC); + return "" + name + " = machine.SoftSPI(baudrate=" + freq + ", sck=machine.Pin(" + sck + "), mosi=machine.Pin(" + mosi + "), miso=machine.Pin(" + miso + "))\n"; +} + +export const communicate_spi_set = function (block, generator) { + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + return "spi.init(baudrate=" + data + ")\n"; +} + +export const communicate_spi_buffer = function (block, generator) { + var varname = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + return "" + varname + "=bytearray(" + data + ")\n"; +} + +export const communicate_spi_read = function (block, generator) { + var varname = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + return ["" + varname + ".read(" + data + ")", generator.ORDER_ATOMIC]; +} + +export const communicate_spi_read_output = function (block, generator) { + var varname = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var val = generator.valueToCode(this, 'val', generator.ORDER_ATOMIC); + return ["" + varname + ".read(" + data + ", " + val + ")", generator.ORDER_ATOMIC]; +} + +export const communicate_spi_readinto = function (block, generator) { + var varname = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + return ["" + varname + ".readinto(" + data + ")", generator.ORDER_ATOMIC]; +} + +export const communicate_spi_readinto_output = function (block, generator) { + var varname = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var val = generator.valueToCode(this, 'val', generator.ORDER_ATOMIC); + return ["" + varname + ".readinto(" + data + ", " + val + ")", generator.ORDER_ATOMIC]; +} + +export const communicate_spi_write = function (block, generator) { + var varname = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + return ["" + varname + ".write(" + data + ".encode('utf-8'))", generator.ORDER_ATOMIC]; +} + +export const communicate_spi_write_readinto = function (block, generator) { + var varname = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var val = generator.valueToCode(this, 'val', generator.ORDER_ATOMIC); + // var op=this.getFieldValue('op'); + // if(op=="byte"){ + return ["" + varname + ".write_readinto(" + data + ".encode('utf-8'), " + val + ")", generator.ORDER_ATOMIC]; + // }else{ + // return [""+varname+".write_readinto(" + data + ","+val+")", generator.ORDER_ATOMIC]; + // } +} + +export const communicate_ow_init = function (block, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_onewire'] = "import onewire"; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var varName = generator.valueToCode(this, 'BUS', generator.ORDER_ATOMIC); + var code = "" + name + "=onewire.OneWire(machine.Pin(" + varName + "))\n"; + return code; +} + +export const communicate_ow_scan = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + name + ".scan()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_ow_reset = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + name + ".reset()\n"; + return code; +} + +export const communicate_ow_read = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + name + ".readbyte()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_ow_write = function (block, generator) { + var varName = generator.valueToCode(this, 'byte', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var op = this.getFieldValue('op'); + var code = "" + name + "." + op + "(" + varName + ")\n"; + return code; +} + +export const communicate_ow_select = function (block, generator) { + var varName = generator.valueToCode(this, 'byte', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + name + ".select_rom(" + varName + ".encode('utf-8'))\n"; + return code; +} + +export const communicate_ir_recv_init = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var bit = this.getFieldValue('type'); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (sub == "" && bit == "RC5") { + var code = "ir_rx = irremote.RC5_RX(" + pin + ")\n"; + }else if (bit == "RC5"){ + var code = "ir_rx = irremote.RC5_RX(" + pin + ", " + sub + ")\n"; + } + else if (sub == "") { + var code = "ir_rx = irremote.NEC_RX(" + pin + ", " + bit + ")\n"; + } + else { + var code = "ir_rx = irremote.NEC_RX(" + pin + ", " + bit + ", " + sub + ")\n"; + } + return code; +} + +export const internal_variable = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var index = this.getFieldValue('index'); + var code = "ir_rx.code[" + index + "]"; + return [code, generator.ORDER_ATOMIC]; +} + +export const recv_fun = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var en = this.getFieldValue('en'); + var code = "ir_rx.enable(" + en + ")\n"; + return code; +} + +export const ir_whether_recv = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var code = "ir_rx.any()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const ir_recv_timeout = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + var code = "ir_rx.timeout(" + time + ")\n"; + return code; +} + +export const communicate_ir_send_init = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var sam = this.getFieldValue('type'); + var power = generator.valueToCode(this, 'power', generator.ORDER_ATOMIC); + if (sam == "RC5") { + var code = "ir_tx = irremote.RC5_TX(" + pin + ", " + power + ")\n"; + } + else { + var code = "ir_tx = irremote.NEC_TX(" + pin + ", " + sam + ", " + power + ")\n"; + } + return code; +} + +export const ir_transmit_conventional_data = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var cmd = generator.valueToCode(this, 'cmd', generator.ORDER_ATOMIC); + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var toggle = generator.valueToCode(this, 'toggle', generator.ORDER_ATOMIC); + var code = "ir_tx.transmit(" + cmd + ", " + addr + ", " + toggle + ")\n"; + return code; +} + +export const ir_transmit_study_code = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var s_code = generator.valueToCode(this, 'LIST', generator.ORDER_ATOMIC); + var code = "ir_tx.transmit(pulses=" + s_code + ")\n"; + return code; +} + +export const ir_transmit_raw_code = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var raw = generator.valueToCode(this, 'raw', generator.ORDER_ATOMIC); + var code = "ir_tx.transmit(raw=" + raw + ")\n"; + return code; +} + +export const ir_transmit_busy = function (block, generator) { + generator.definitions_['import_irremote'] = 'import irremote'; + var code = "ir_tx.busy()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_bluetooth_central_init = function (block, generator) { + generator.definitions_['import_ble_central'] = 'import ble_central'; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + " = ble_central.BLESimpleCentral()\n"; + return code; +} + +export const communicate_bluetooth_peripheral_init = function (block, generator) { + generator.definitions_['import_ble_peripheral'] = 'import ble_peripheral'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + " = ble_peripheral.BLESimplePeripheral(" + data + ")\n"; + return code; +} + +export const communicate_bluetooth_scan = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + ".scan()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_bluetooth_connect = function (block, generator) { + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('mode'); + var code = name + ".connect(" + mode + '=' + data + ")\n"; + return code; +} + +export const communicate_bluetooth_disconnect = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + '.disconnect()\n'; + return code; +} + +export const communicate_bluetooth_mac = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return [name + ".mac", generator.ORDER_ATOMIC]; +} + +export const communicate_bluetooth_is_connected = function (block, generator) { + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + ".is_connected()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_bluetooth_send = function (block, generator) { + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + ".send(" + data + ")\n"; + return code; +} + +export const communicate_bluetooth_recv_only = function (block, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = v + '.recv()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const communicate_bluetooth_recv = function (block, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var method = generator.valueToCode(this, 'METHOD', generator.ORDER_ATOMIC); + var code = v + '.recv(' + method + ')\n'; + return code; +} + +export const communicate_bluetooth_handle = function (block, generator) { + generator.definitions_['import_ble_handle'] = 'import ble_handle'; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var method = generator.valueToCode(this, 'METHOD', generator.ORDER_ATOMIC); + var code = v + '=ble_handle.Handle()\n' + v + '.recv(' + method + ')\n'; + return code; +} + +//espnow +export const communicate_espnow_init = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var varName = generator.valueToCode(this, 'CHNL', generator.ORDER_ATOMIC); + var power = this.getFieldValue('op'); + var code = "" + name + "=radio.ESPNow(channel=" + varName + ", txpower=" + power + ")\n"; + return code; +} + +export const communicate_espnow_init_new = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var varName = generator.valueToCode(this, 'CHNL', generator.ORDER_ATOMIC); + var varName2 = generator.valueToCode(this, 'DB', generator.ORDER_ATOMIC); + var code = "" + name + "=radio.ESPNow(channel=" + varName + ', txpower=' + varName2 + ")\n"; + return code; +} + +export const network_espnow_mac = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return [name + ".mac", generator.ORDER_ATOMIC]; +} + +export const network_espnow_info = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return [name + ".info()", generator.ORDER_ATOMIC]; +} + +export const network_espnow_recv = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var mode = this.getFieldValue('mode'); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + ".recv()" + mode; + return [code, generator.ORDER_ATOMIC]; +} + +export const network_espnow_send = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var mac = generator.valueToCode(this, 'mac', generator.ORDER_ATOMIC); + var content = generator.valueToCode(this, 'content', generator.ORDER_ATOMIC); + var code = name + ".send(" + mac + ", " + content + ")\n"; + return code; +} + +export const network_espnow_recv_handle = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var method = generator.valueToCode(this, 'METHOD', generator.ORDER_ATOMIC); + var code = name + ".recv_cb(" + method + ")\n"; + return code; +} + +//radio +export const espnow_radio_channel = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + generator.definitions_['var_declare_ESPNow_radio'] = "ESPNow_radio=radio.ESPNow()"; + var varName = generator.valueToCode(this, 'CHNL', generator.ORDER_ATOMIC); + var code = "ESPNow_radio.set_channel(channel=" + varName + ")\n"; + return code; +} + +export const espnow_radio_txpower = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + generator.definitions_['var_declare_ESPNow_radio'] = "ESPNow_radio=radio.ESPNow()"; + var power = this.getFieldValue('op'); + var code = "ESPNow_radio.set_channel(txpower=" + power + ")\n"; + return code; +} + +export const espnow_radio_channel_new = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + var varName2 = generator.valueToCode(this, 'DB', generator.ORDER_ATOMIC); + generator.definitions_['var_declare_ESPNow_radio'] = "ESPNow_radio=radio.ESPNow(channel=1, txpower=" + varName2 + ")"; + var varName = generator.valueToCode(this, 'CHNL', generator.ORDER_ATOMIC); + var code = "ESPNow_radio.set_channel(" + varName + ")\n"; + return code; +} + +export const espnow_radio_on_off = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + generator.definitions_['var_declare_ESPNow_radio'] = 'ESPNow_radio = radio.ESPNow()'; + var op = this.getFieldValue('on_off'); + var code = "ESPNow_radio.active(" + op + ")\n"; + return code; +} + +export const espnow_radio_send = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + generator.definitions_['var_declare_ESPNow_radio'] = 'ESPNow_radio = radio.ESPNow()'; + var varName = generator.valueToCode(this, 'send', generator.ORDER_ATOMIC); + var code = 'ESPNow_radio.send("ffffffffffff",' + varName + ")\n"; + return code; +} + +export const espnow_radio_rec = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + generator.definitions_['var_declare_ESPNow_radio'] = 'ESPNow_radio = radio.ESPNow()'; + var code = "ESPNow_radio.recv()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const espnow_radio_recv_msg = function (block, generator) { + var code = "ESPNow_radio_msg"; + return [code, generator.ORDER_ATOMIC]; +} + +export const espnow_radio_recv = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + generator.definitions_['import_ubinascii'] = 'import ubinascii'; + generator.definitions_['var_declare_ESPNow_radio'] = 'ESPNow_radio = radio.ESPNow()'; + var doCode = generator.statementToCode(block, 'DO') || generator.PASS; + generator.definitions_['def_ESPNow_radio_recv'] = 'def ESPNow_radio_recv(mac,ESPNow_radio_msg):\n' + doCode; + generator.definitions_['def_ESPNow_radio_recv_all'] = '_radio_msg_list = []\n' + + 'def ESPNow_radio_recv_callback(mac,ESPNow_radio_msg):\n' + + ' global _radio_msg_list\n' + + ' try:\n' + + ' ESPNow_radio_recv(mac,ESPNow_radio_msg)\n' + + ' except:\n' + + ' pass\n' + + ' if str(ESPNow_radio_msg) in _radio_msg_list:\n' + + " eval('radio_recv_' + bytes.decode(ubinascii.hexlify(ESPNow_radio_msg)) + '()')\n"; + generator.definitions_['ESPNow_radio_recv_callback'] = "ESPNow_radio.recv_cb(ESPNow_radio_recv_callback)\n"; + + return ''; +} + +var writeUTF = function (str, isGetBytes) { + var back = []; + var byteSize = 0; + for (var i = 0; i < str.length; i++) { + var code = str.charCodeAt(i); + if (0x00 <= code && code <= 0x7f) { + byteSize += 1; + back.push(code); + } else if (0x80 <= code && code <= 0x7ff) { + byteSize += 2; + back.push((192 | (31 & (code >> 6)))); + back.push((128 | (63 & code))) + } else if ((0x800 <= code && code <= 0xd7ff) || (0xe000 <= code && code <= 0xffff)) { + byteSize += 3; + back.push((224 | (15 & (code >> 12)))); + back.push((128 | (63 & (code >> 6)))); + back.push((128 | (63 & code))) + } + } + for (i = 0; i < back.length; i++) { + back[i] &= 0xff; + } + if (isGetBytes) { + return back; + } + if (byteSize <= 0xff) { + return [0, byteSize].concat(back); + } + return [byteSize >> 8, byteSize & 0xff].concat(back); +} + +var toUTF8Hex = function (str) { + var charBuf = writeUTF(str, true); + var re = ''; + for (var i = 0; i < charBuf.length; i++) { + var x = (charBuf[i] & 0xFF).toString(16); + if (x.length === 1) { + x = '0' + x; + } + re += x; + } + return re; +} + +export const espnow_radio_recv_certain_msg = function (block, generator) { + generator.definitions_['import_radio'] = "import radio"; + generator.definitions_['import_ubinascii'] = 'import ubinascii'; + generator.definitions_['var_declare_ESPNow_radio'] = 'ESPNow_radio = radio.ESPNow()'; + var doCode = generator.statementToCode(block, 'DO') || generator.PASS; + generator.definitions_['def_ESPNow_radio_recv_all'] = '_radio_msg_list = []\n' + + 'def ESPNow_radio_recv_callback(mac,ESPNow_radio_msg):\n' + + ' global _radio_msg_list\n' + + ' try:\n' + + ' ESPNow_radio_recv(mac,ESPNow_radio_msg)\n' + + ' except:\n' + + ' pass\n' + + ' if str(ESPNow_radio_msg) in _radio_msg_list:\n' + + " eval('radio_recv_' + bytes.decode(ubinascii.hexlify(ESPNow_radio_msg)) + '()')\n"; + generator.definitions_['ESPNow_radio_recv_callback'] = "ESPNow_radio.recv_cb(ESPNow_radio_recv_callback)\n"; + var message = block.getFieldValue('msg'); + var message_utf8 = toUTF8Hex(message); + generator.definitions_['def_radio_recv_' + message_utf8] = + '_radio_msg_list.append(\'' + message + '\')\n' + + 'def radio_recv_' + message_utf8 + '():\n' + doCode; + return ''; +} + +export const espnow_radio_recv_new = function (block, generator) { + generator.definitions_['import_radio'] = 'import radio'; + generator.definitions_['var_declare_ESPNow_radio'] = 'ESPNow_radio = radio.ESPNow()'; + var doCode = generator.statementToCode(block, 'DO') || generator.PASS; + generator.definitions_['def_ESPNow_radio_recv'] = 'def ESPNow_radio_recv(mac, ESPNow_radio_msg):\n' + + `${doCode}\nESPNow_radio.recv_cb("__all__", ESPNow_radio_recv)\n`; + return ''; +} + +export const espnow_radio_recv_certain_msg_new = function (block, generator) { + generator.definitions_['import_radio'] = 'import radio'; + generator.definitions_['var_declare_ESPNow_radio'] = 'ESPNow_radio = radio.ESPNow()'; + var doCode = generator.statementToCode(block, 'DO') || generator.PASS; + var message = block.getFieldValue('msg'); + generator.definitions_['def_ESPNow_radio_recv_' + message] = 'def ESPNow_radio_recv(mac, ESPNow_radio_msg):\n' + + `${doCode}\nESPNow_radio.recv_cb("${message}", ESPNow_radio_recv)\n`; + return ''; +} + +export const lora_init = function (block, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sv = generator.valueToCode(this, 'SPISUB', generator.ORDER_ATOMIC); + var pv = generator.valueToCode(this, 'PINSUB', generator.ORDER_ATOMIC); + var fr = generator.valueToCode(this, 'frequency', generator.ORDER_ATOMIC); + var r = generator.valueToCode(this, 'rate', generator.ORDER_ATOMIC); + var f = generator.valueToCode(this, 'factor', generator.ORDER_ATOMIC); + var p = generator.valueToCode(this, 'power', generator.ORDER_ATOMIC); + var bandwidth = this.getFieldValue('bandwidth'); + var code; + generator.definitions_['import_rfm98'] = 'import rfm98'; + var code = v + ' = rfm98.RFM98(' + sv + ', cs_pin=' + pv + ', frequency_mhz=' + fr + ', signal_bandwidth=' + bandwidth + ', coding_rate=' + r + ', spreading_factor=' + f + ', tx_power=' + p + ')\n'; + return code; +} + +export const lora_packet = function (block, generator) { + generator.definitions_['import_rfm98'] = 'import rfm98'; + var key = this.getFieldValue('key'); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return [name + "." + key + '()', generator.ORDER_ATOMIC]; +} + +export const lora_send = function (block, generator) { + generator.definitions_['import_rfm98'] = 'import rfm98'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = name + ".send(" + data + ")\n"; + return code; +} + +export const lora_recv = function (block, generator) { + generator.definitions_['import_rfm98'] = 'import rfm98'; + var name = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return [name + '.recv()', generator.ORDER_ATOMIC]; +} + +export const urequests_get = function (block, generator) { + generator.definitions_.import_requests = "import urequests"; + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var str = generator.valueToCode(this, 'DOMAIN', generator.ORDER_ATOMIC); + var code = varName + '= ' + 'urequests.get(' + str + ')\n'; + return code; +} + +export const urequests_attribute = function (block, generator) { + generator.definitions_.import_requests = "import urequests"; + var varName = generator.valueToCode(this, 'VAL', generator.ORDER_ASSIGNMENT) || '0'; + var attr = this.getFieldValue('ATTR'); + var code = varName + "." + attr; + return [code, generator.ORDER_ATOMIC]; +} + +export const urequests_method = function (block, generator) { + generator.definitions_.import_requests = "import urequests"; + var method = this.getFieldValue('DIR'); + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "urequests." + method + "(" + str + ')'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/control.js b/mixly/boards/default_src/micropython/generators/control.js new file mode 100644 index 00000000..894ec4fe --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/control.js @@ -0,0 +1,119 @@ +import * as Blockly from 'blockly/core'; +import { controls_repeat_ext } from '@mixly/python/generators/control'; + +export const base_setup = function (_, generator) { + var branch = generator.statementToCode(this, 'DO'); + branch = branch.replace(/(^\s*)|(\s*$)/g, "").replace(/\n {4}/g, '\n');//去除两端空格 + if (branch) { + if (branch.endsWith('\n')) { + generator.setups_['setup_setup'] = branch; + } else { + generator.setups_['setup_setup'] = branch + '\n'; + } + } + return ''; +} + +// ok +export const controls_if = function (a, generator) { + var b = 0, + c = "", + d, + e; + do + e = generator.valueToCode(a, "IF" + b, generator.ORDER_NONE) || "False", d = generator.statementToCode(a, "DO" + b) || generator.PASS, c += (0 == b ? "if " : "elif ") + e + ":\n" + d, ++b; + while (a.getInput("IF" + b)); + a.getInput("ELSE") && (d = generator.statementToCode(a, "ELSE") || generator.PASS, c += "else:\n" + d); + return c +} + +// ok +export const controls_for = function (a, generator) { + var b = generator.variableDB_.getName(a.getFieldValue("VAR"), Blockly.Variables.NAME_TYPE), + //var b = generator.valueToCode(a, "VAR", generator.ORDER_MEMBER) || "''", + c = generator.valueToCode(a, "FROM", generator.ORDER_NONE) || "0", + d = generator.valueToCode(a, "TO", generator.ORDER_NONE) || "0", + e = generator.valueToCode(a, "STEP", generator.ORDER_NONE) || "1", + f = generator.addLoopTrap(generator.statementToCode(a, "DO"), a.id) || generator.PASS, + g = "", + h = function (_, generator) { + return generator.provideFunction_("upRange", + ["def " + generator.FUNCTION_NAME_PLACEHOLDER_ + "(start, stop, step):", " while start <= stop:", " yield start", " start += abs(step)"]) + }, + k = function (_, generator) { + return generator.provideFunction_("downRange", ["def " + generator.FUNCTION_NAME_PLACEHOLDER_ + "(start, stop, step):", " while start >= stop:", " yield start", " start -= abs(step)"]) + } + a = function (a, b, c) { + return "(" + a + " <= " + b + ") and " + h() + "(" + a + ", " + b + ", " + c + ") or " + k() + "(" + a + ", " + b + ", " + c + ")" + } + if (Blockly.isNumber(c) && Blockly.isNumber(d) && + Blockly.isNumber(e)) + c = parseFloat(c), d = parseFloat(d), e = Math.abs(parseFloat(e)), 0 === c % 1 && 0 === d % 1 && 0 === e % 1 ? (c <= d ? (d++, a = 0 == c && 1 == e ? d : c + ", " + d, 1 != e && (a += ", " + e)) : (d--, a = c + ", " + d + ", -" + e), a = "range(" + a + ")") : (a = c < d ? h() : k(), a += "(" + c + ", " + d + ", " + e + ")"); + else { + var l = function (a, c) { + if (Blockly.isNumber(a)) + a = parseFloat(a); + else { + var d = generator.variableDB_.getDistinctName(b + c, Blockly.Variables.NAME_TYPE); + g += d + " = " + a + "\n"; + a = d + } + return a + } + c = l(c, "_start"); + d = l(d, "_end"); + l(e, "_inc"); + a = "number" == typeof c && "number" == typeof d ? c < d ? h(c, d, e) : k(c, d, e) : a(c, d, e) + } + return g += "for " + b + " in " + a + ":\n" + f +} + +// ok +export const controls_repeat = controls_repeat_ext; + +export const controls_whileUntil = function (a, generator) { + var b = "UNTIL" == a.getFieldValue("MODE"), + c = generator.valueToCode(a, "BOOL", b ? generator.ORDER_LOGICAL_NOT : generator.ORDER_NONE) || "False", + d = generator.addLoopTrap(generator.statementToCode(a, "DO"), a.id) || generator.PASS; + b && (c = "not " + c); + return "while " + c + ":\n" + d +} + +// ok +export const controls_flow_statements = function (a) { + switch (a.getFieldValue("FLOW")) { + case "BREAK": + return "break\n"; + case "CONTINUE": + return "continue\n" + } + throw "Unknown flow statement."; +} + +//ok +export const controls_forEach = function (block, generator) { + // For each loop. + var variable0 = generator.variableDB_.getName( + block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = generator.valueToCode(block, 'LIST', + generator.ORDER_RELATIONAL) || '[]'; + var branch = generator.statementToCode(block, 'DO'); + branch = generator.addLoopTrap(branch, block.id) || + generator.PASS; + var code = 'for ' + variable0 + ' in ' + argument0 + ':\n' + branch; + return code; +} + +// ok +export const controls_type = function (_, generator) { + var data = generator.valueToCode(this, 'DATA', generator.ORDER_ATOMIC) || '1000' + var code = 'type(' + data + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const controls_typeLists = function (_, generator) { + generator.definitions_['import_microbit_*'] = 'from microbit import *'; + var type = this.getFieldValue('type'); + // generator.definitions_['func_type' + type] = code; + return [type, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/display.js b/mixly/boards/default_src/micropython/generators/display.js new file mode 100644 index 00000000..2310c5b3 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/display.js @@ -0,0 +1,496 @@ +export const display_show_image_or_string = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "matrix.show(" + data + ")\n"; + return code; +} + +export const display_scroll_string = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "matrix.scroll(" + data + ")\n"; + return code; +} + +export const display_show_static = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "matrix.showstatic(" + data + ")\n"; + return code; +} + +export const display_show_image_or_string_delay = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var code = "matrix.show(" + data + ', ' + time + ")\n"; + return code; +} + +export const display_scroll_string_delay = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var code = "matrix.scroll(" + data + ', ' + time + ")\n"; + return code; +} + +export const display_image_create = function (block, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var colours = { + "#000000": "0", + //"#440000": "1", + //"#660000": "2", + //"#880000": "3", + //"#aa0000": "4", + //"#bb0000": "5", + //"#cc0000": "6", + //"#dd0000": "7", + //"#ee0000": "8", + "#ff0000": "1" + } + var colour_00 = colours[block.getFieldValue("00")]; + var colour_01 = colours[block.getFieldValue("01")]; + var colour_02 = colours[block.getFieldValue("02")]; + var colour_03 = colours[block.getFieldValue("03")]; + var colour_04 = colours[block.getFieldValue("04")]; + var colour_05 = colours[block.getFieldValue("05")]; + var colour_06 = colours[block.getFieldValue("06")]; + var colour_07 = colours[block.getFieldValue("07")]; + var colour_08 = colours[block.getFieldValue("08")]; + var colour_09 = colours[block.getFieldValue("09")]; + var colour_0a = colours[block.getFieldValue("0a")]; + var colour_0b = colours[block.getFieldValue("0b")]; + var colour_0c = colours[block.getFieldValue("0c")]; + var colour_0d = colours[block.getFieldValue("0d")]; + var colour_0e = colours[block.getFieldValue("0e")]; + var colour_0f = colours[block.getFieldValue("0f")]; + var colour_10 = colours[block.getFieldValue("10")]; + var colour_11 = colours[block.getFieldValue("11")]; + var colour_12 = colours[block.getFieldValue("12")]; + var colour_13 = colours[block.getFieldValue("13")]; + var colour_14 = colours[block.getFieldValue("14")]; + var colour_15 = colours[block.getFieldValue("15")]; + var colour_16 = colours[block.getFieldValue("16")]; + var colour_17 = colours[block.getFieldValue("17")]; + var colour_18 = colours[block.getFieldValue("18")]; + var colour_19 = colours[block.getFieldValue("19")]; + var colour_1a = colours[block.getFieldValue("1a")]; + var colour_1b = colours[block.getFieldValue("1b")]; + var colour_1c = colours[block.getFieldValue("1c")]; + var colour_1d = colours[block.getFieldValue("1d")]; + var colour_1e = colours[block.getFieldValue("1e")]; + var colour_1f = colours[block.getFieldValue("1f")]; + var colour_20 = colours[block.getFieldValue("20")]; + var colour_21 = colours[block.getFieldValue("21")]; + var colour_22 = colours[block.getFieldValue("22")]; + var colour_23 = colours[block.getFieldValue("23")]; + var colour_24 = colours[block.getFieldValue("24")]; + var colour_25 = colours[block.getFieldValue("25")]; + var colour_26 = colours[block.getFieldValue("26")]; + var colour_27 = colours[block.getFieldValue("27")]; + var colour_28 = colours[block.getFieldValue("28")]; + var colour_29 = colours[block.getFieldValue("29")]; + var colour_2a = colours[block.getFieldValue("2a")]; + var colour_2b = colours[block.getFieldValue("2b")]; + var colour_2c = colours[block.getFieldValue("2c")]; + var colour_2d = colours[block.getFieldValue("2d")]; + var colour_2e = colours[block.getFieldValue("2e")]; + var colour_2f = colours[block.getFieldValue("2f")]; + var colour_30 = colours[block.getFieldValue("30")]; + var colour_31 = colours[block.getFieldValue("31")]; + var colour_32 = colours[block.getFieldValue("32")]; + var colour_33 = colours[block.getFieldValue("33")]; + var colour_34 = colours[block.getFieldValue("34")]; + var colour_35 = colours[block.getFieldValue("35")]; + var colour_36 = colours[block.getFieldValue("36")]; + var colour_37 = colours[block.getFieldValue("37")]; + var colour_38 = colours[block.getFieldValue("38")]; + var colour_39 = colours[block.getFieldValue("39")]; + var colour_3a = colours[block.getFieldValue("3a")]; + var colour_3b = colours[block.getFieldValue("3b")]; + var colour_3c = colours[block.getFieldValue("3c")]; + var colour_3d = colours[block.getFieldValue("3d")]; + var colour_3e = colours[block.getFieldValue("3e")]; + var colour_3f = colours[block.getFieldValue("3f")]; + var colour_40 = colours[block.getFieldValue("40")]; + var colour_41 = colours[block.getFieldValue("41")]; + var colour_42 = colours[block.getFieldValue("42")]; + var colour_43 = colours[block.getFieldValue("43")]; + var colour_44 = colours[block.getFieldValue("44")]; + var colour_45 = colours[block.getFieldValue("45")]; + var colour_46 = colours[block.getFieldValue("46")]; + var colour_47 = colours[block.getFieldValue("47")]; + var colour_48 = colours[block.getFieldValue("48")]; + var colour_49 = colours[block.getFieldValue("49")]; + var colour_4a = colours[block.getFieldValue("4a")]; + var colour_4b = colours[block.getFieldValue("4b")]; + var colour_4c = colours[block.getFieldValue("4c")]; + var colour_4d = colours[block.getFieldValue("4d")]; + var colour_4e = colours[block.getFieldValue("4e")]; + var colour_4f = colours[block.getFieldValue("4f")]; + var colour_50 = colours[block.getFieldValue("50")]; + var colour_51 = colours[block.getFieldValue("51")]; + var colour_52 = colours[block.getFieldValue("52")]; + var colour_53 = colours[block.getFieldValue("53")]; + var colour_54 = colours[block.getFieldValue("54")]; + var colour_55 = colours[block.getFieldValue("55")]; + var colour_56 = colours[block.getFieldValue("56")]; + var colour_57 = colours[block.getFieldValue("57")]; + var colour_58 = colours[block.getFieldValue("58")]; + var colour_59 = colours[block.getFieldValue("59")]; + var colour_5a = colours[block.getFieldValue("5a")]; + var colour_5b = colours[block.getFieldValue("5b")]; + var colour_5c = colours[block.getFieldValue("5c")]; + var colour_5d = colours[block.getFieldValue("5d")]; + var colour_5e = colours[block.getFieldValue("5e")]; + var colour_5f = colours[block.getFieldValue("5f")]; + var colour_60 = colours[block.getFieldValue("60")]; + var colour_61 = colours[block.getFieldValue("61")]; + var colour_62 = colours[block.getFieldValue("62")]; + var colour_63 = colours[block.getFieldValue("63")]; + var colour_64 = colours[block.getFieldValue("64")]; + var colour_65 = colours[block.getFieldValue("65")]; + var colour_66 = colours[block.getFieldValue("66")]; + var colour_67 = colours[block.getFieldValue("67")]; + var colour_68 = colours[block.getFieldValue("68")]; + var colour_69 = colours[block.getFieldValue("69")]; + var colour_6a = colours[block.getFieldValue("6a")]; + var colour_6b = colours[block.getFieldValue("6b")]; + var colour_6c = colours[block.getFieldValue("6c")]; + var colour_6d = colours[block.getFieldValue("6d")]; + var colour_6e = colours[block.getFieldValue("6e")]; + var colour_6f = colours[block.getFieldValue("6f")]; + var colour_70 = colours[block.getFieldValue("70")]; + var colour_71 = colours[block.getFieldValue("71")]; + var colour_72 = colours[block.getFieldValue("72")]; + var colour_73 = colours[block.getFieldValue("73")]; + var colour_74 = colours[block.getFieldValue("74")]; + var colour_75 = colours[block.getFieldValue("75")]; + var colour_76 = colours[block.getFieldValue("76")]; + var colour_77 = colours[block.getFieldValue("77")]; + var colour_78 = colours[block.getFieldValue("78")]; + var colour_79 = colours[block.getFieldValue("79")]; + var colour_7a = colours[block.getFieldValue("7a")]; + var colour_7b = colours[block.getFieldValue("7b")]; + var colour_7c = colours[block.getFieldValue("7c")]; + var colour_7d = colours[block.getFieldValue("7d")]; + var colour_7e = colours[block.getFieldValue("7e")]; + var colour_7f = colours[block.getFieldValue("7f")]; + var code = 'matrix.Image("' + colour_00 + colour_01 + colour_02 + colour_03 + colour_04 + colour_05 + colour_06 + colour_07 + colour_08 + colour_09 + colour_0a + colour_0b + colour_0c + colour_0d + colour_0e + colour_0f + ':' + colour_10 + colour_11 + colour_12 + colour_13 + colour_14 + colour_15 + colour_16 + colour_17 + colour_18 + colour_19 + colour_1a + colour_1b + colour_1c + colour_1d + colour_1e + colour_1f + ':' + colour_20 + colour_21 + colour_22 + colour_23 + colour_24 + colour_25 + colour_26 + colour_27 + colour_28 + colour_29 + colour_2a + colour_2b + colour_2c + colour_2d + colour_2e + colour_2f + ':' + colour_30 + colour_31 + colour_32 + colour_33 + colour_34 + colour_35 + colour_36 + colour_37 + colour_38 + colour_39 + colour_3a + colour_3b + colour_3c + colour_3d + colour_3e + colour_3f + ':' + colour_40 + colour_41 + colour_42 + colour_43 + colour_44 + colour_45 + colour_46 + colour_47 + colour_48 + colour_49 + colour_4a + colour_4b + colour_4c + colour_4d + colour_4e + colour_4f + ':' + colour_50 + colour_51 + colour_52 + colour_53 + colour_54 + colour_55 + colour_56 + colour_57 + colour_58 + colour_59 + colour_5a + colour_5b + colour_5c + colour_5d + colour_5e + colour_5f + ':' + colour_60 + colour_61 + colour_62 + colour_63 + colour_64 + colour_65 + colour_66 + colour_67 + colour_68 + colour_69 + colour_6a + colour_6b + colour_6c + colour_6d + colour_6e + colour_6f + ':' + colour_70 + colour_71 + colour_72 + colour_73 + colour_74 + colour_75 + colour_76 + colour_77 + colour_78 + colour_79 + colour_7a + colour_7b + colour_7c + colour_7d + colour_7e + colour_7f + '")'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_image_builtins = function (block, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var dropdown_image = block.getFieldValue('image'); + var code = 'matrix.Image.' + dropdown_image; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_get_pixel = function (block, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var value_x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var value_y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var code = 'matrix.get_pixel(int(' + value_x + '), int(' + value_y + '))'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_bright_point = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = 'matrix.set_pixel(int(' + x + '), int(' + y + '), ' + dropdown_stat + ")\n"; + return code; +} + +export const display_get_screen_pixel = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var code = 'matrix.get_brightness()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_get_screen_image = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var code = 'matrix.get_screenimage()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_bright_screen = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var code = 'matrix.set_brightness(' + x + ')\n'; + return code; +} + +export const display_blink_rate = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var code = 'matrix.blink_rate(' + x + ')\n'; + return code; +} + +export const display_clear = function (_, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var code = 'matrix.clear()\n'; + return code; +} + +export const display_use_i2c_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var i2csub = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC); + var column = generator.valueToCode(this, 'column', generator.ORDER_ATOMIC); + var code = sub + " = ssd1306.SSD1306_I2C(" + row + ", " + column + ", " + i2csub + ")\n"; + return code; +} + +export const display_draw_4strings = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var value_text_line1 = generator.valueToCode(this, 'Text_line1', generator.ORDER_ASSIGNMENT) || '\'\''; + var value_text_line2 = generator.valueToCode(this, 'Text_line2', generator.ORDER_ASSIGNMENT) || '\'\''; + var value_text_line3 = generator.valueToCode(this, 'Text_line3', generator.ORDER_ASSIGNMENT) || '\'\''; + var value_text_line4 = generator.valueToCode(this, 'Text_line4', generator.ORDER_ASSIGNMENT) || '\'\''; + var code = varName + '.show_str(' + value_text_line1 + ', ' + value_text_line2 + ', ' + value_text_line3 + ', ' + value_text_line4 + ')\n' + return code; +} + +export const display_line_arbitrarily = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x1 = generator.valueToCode(this, 'x1', generator.ORDER_ATOMIC); + var location_y1 = generator.valueToCode(this, 'y1', generator.ORDER_ATOMIC); + var location_x2 = generator.valueToCode(this, 'x2', generator.ORDER_ATOMIC); + var location_y2 = generator.valueToCode(this, 'y2', generator.ORDER_ATOMIC); + var code = varName + '.show_line(' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', 1)\n'; + return code; +} + +export const display_rect = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var value_width = generator.valueToCode(this, 'width', generator.ORDER_ATOMIC); + var value_height = generator.valueToCode(this, 'height', generator.ORDER_ATOMIC); + var checkbox_fill = this.getFieldValue("fill") == 'TRUE' ? 'True' : 'False'; + var size = this.getFieldValue('OP'); + var code = ''; + switch (checkbox_fill) { + case "True": + code = varName + '.show_fill_rect(' + location_x + ', ' + location_y + ', ' + value_width + ', ' + value_height + ', ' + size + ')\n'; + break; + case "False": + code = varName + '.show_rect(' + location_x + ', ' + location_y + ', ' + value_width + ', ' + value_height + ', ' + size + ')\n'; + break; + } + return code; +} + +export const image_arithmetic = function (block, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var op = block.getFieldValue("OP"); + var imga = generator.valueToCode(block, 'A', generator.ORDER_ATOMIC); + var imgb = generator.valueToCode(block, 'B', generator.ORDER_ATOMIC); + var code = ''; + if (op == 'INTERSECTION') { + code = imga + '-(' + imga + '-' + imgb + ')'; + } else { + code = imga + op + imgb; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const display_line = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var value_length = generator.valueToCode(this, 'length', generator.ORDER_ATOMIC); + var value_direction = this.getFieldValue("direction"); + var code = varName + '.show_' + value_direction + '(' + location_x + ', ' + location_y + ', ' + value_length + ', 1)\n'; + return code; +} + +export const display_onoff = function (_, generator) { + var code = (this.getFieldValue('ONOFF') == 'ON') ? '1' : '0'; + return [code, generator.ORDER_ATOMIC]; +} + +export const image_shift = function (block, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var op = block.getFieldValue("OP"); + var image = generator.valueToCode(block, 'img', generator.ORDER_ATOMIC); + var value = generator.valueToCode(block, 'val', generator.ORDER_ATOMIC); + var code = image + '.shift_' + op + '(' + value + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_fill = function (_, generator) { + var varName = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var code = varName + '.show_fill(' + key + ')\n'; + return code; +} + +// export const switch = function (_, generator) { +// var code = this.getFieldValue('flag'); +// return [code, generator.ORDER_ATOMIC]; +// } + +export const display_tm_use_i2c_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue("key"); + var code; + if (key == 'TM1650') { + generator.definitions_['import_tm1650'] = 'import tm1650'; + code = v + ' = tm1650.' + key + "(" + iv + ')\n'; + } else if (key == 'TM1637') { + generator.definitions_['import_tm1637'] = 'import tm1637'; + code = v + ' = tm1637.' + key + "(" + iv + ')\n'; + } + return code; +} + +export const display_tm1650_power = function (_, generator) { + var type = this.getFieldValue("TYPE"); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var stat = this.getFieldValue("STAT"); + var code = v + '.' + type + stat + "()\n"; + return code; +} + +export const display_tm1650_show_num = function (_, generator) { + var type = this.getFieldValue("TYPE"); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var val = generator.valueToCode(this, 'VALUE', generator.ORDER_ATOMIC); + var code = v + '.' + type + "_show_num(" + val + ")\n"; + return code; +} + +export const display_tm1650_show_dot = function (_, generator) { + var type = this.getFieldValue("TYPE"); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var n = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + var stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = v + '.' + type + "_show_dot(" + n + ", " + stat + ")\n"; + return code; +} + +export const display_animate = function (_, generator) { + // Boolean values true and false. + var name = this.getFieldValue("ANIMATION"); + var code = 'matrix.Image.' + name; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_circle = function (_, generator) { + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var location_x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var value_r = generator.valueToCode(this, 'r', generator.ORDER_ATOMIC); + var checkbox_fill = this.getFieldValue("fill") == 'TRUE' ? 'True' : 'False'; + var size = this.getFieldValue('OP'); + var code = ''; + switch (checkbox_fill) { + case "True": + code = varName + '.show_fill_circle(' + location_x + ', ' + location_y + ', ' + value_r + ', ' + size + ')\n'; + break; + case "False": + code = varName + '.show_circle(' + location_x + ', ' + location_y + ', ' + value_r + ', ' + size + ')\n'; + break; + } + return code; +} + +export const display_triangle = function (_, generator) { + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var location_x0 = generator.valueToCode(this, 'x0', generator.ORDER_ATOMIC); + var location_y0 = generator.valueToCode(this, 'y0', generator.ORDER_ATOMIC); + var location_x1 = generator.valueToCode(this, 'x1', generator.ORDER_ATOMIC); + var location_y1 = generator.valueToCode(this, 'y1', generator.ORDER_ATOMIC); + var location_x2 = generator.valueToCode(this, 'x2', generator.ORDER_ATOMIC); + var location_y2 = generator.valueToCode(this, 'y2', generator.ORDER_ATOMIC); + var checkbox_fill = this.getFieldValue("fill") == 'TRUE' ? 'True' : 'False'; + var size = this.getFieldValue('OP'); + var code = ''; + switch (checkbox_fill) { + case "True": + code = varName + '.show_fill_triangle(' + location_x0 + ', ' + location_y0 + ', ' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', ' + size + ')\n'; + break; + case "False": + code = varName + '.show_triangle(' + location_x0 + ', ' + location_y0 + ', ' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', ' + size + ')\n'; + break; + } + return code; +} + +export const display_oled_showBitmap = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'START_X', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'START_Y', generator.ORDER_ATOMIC); + var bmp = generator.valueToCode(this, 'bitmap_name', generator.ORDER_ATOMIC); + var w = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC); + var h = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC); + var code = varName + '.show_bitmap(' + location_x + ', ' + location_y + ', ' + bmp + ', ' + w + ', ' + h + ')\n'; + return code; +} + +export const display_oled_drawPixel = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'POS_X', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'POS_Y', generator.ORDER_ATOMIC); + var code = varName + '.show_pixel(' + location_x + ', ' + location_y + ')\n'; + return code; +} + +// pe: +export const display_matrix_use_i2c_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue("key"); + var code; + if (key == '32x12 Matrix') { + generator.definitions_['import_matrix32x12'] = 'import matrix32x12'; + code = v + ' = matrix32x12.Matrix(' + iv + ')\n'; + } else if (key == 'TM1637') { + generator.definitions_['import_tm1637'] = 'import tm1637'; + code = v + ' = tm1637.' + key + "(" + iv + ')\n'; + } + return code; +} + +export const display_show_image = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_matrix32x12'] = 'import matrix32x12'; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".set_buffer(" + data + ")\n"; + return code; +} + +export const display_scroll_string_extern = function (_, generator) { + generator.definitions_['import_matrix32x12'] = 'import matrix32x12'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".scroll(" + data + ")\n"; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/display_extern.js b/mixly/boards/default_src/micropython/generators/display_extern.js new file mode 100644 index 00000000..0cba2754 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/display_extern.js @@ -0,0 +1,726 @@ +import { Boards } from 'mixly'; + +export const display_matrix_use_i2c_init = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue("key"); + var font = ''; + if (['mpython', 'mixgo_pe', 'mixgo_nova'].indexOf(version) >= 0) { + font = '0x700000' + } else if (['mixgo_sant'].indexOf(version) >= 0) { + font = '0xE00000' + } else { + font = '0x3A0000' + } + var code; + if (key == '32x12 Matrix') { + generator.definitions_['import_matrix32x12'] = 'import matrix32x12'; + code = v + ' = matrix32x12.Matrix(' + iv + ', font_address=' + font + ')\n'; + } else if (key == '16x8 Matrix') { + generator.definitions_['import_matrix16x8'] = 'import matrix16x8'; + code = v + ' = matrix16x8.Matrix(' + iv + ')\n'; + } + return code; +} + +export const display_matrix_extern_show_image = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".shows(" + data + ")\n"; + return code; +} + +export const display_matrix_extern_show_image_or_string_delay = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var op = this.getFieldValue('center'); + var code = v + ".shows(" + data + ', space=' + space + ', center=' + op + ")\n"; + return code; +} + +export const display_matrix_extern_show_frame_string = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".frame(" + data + ")\n"; + return code; +} + +export const display_matrix_extern_show_frame_string_delay = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var code = v + ".frame(" + data + ', delay=' + time + ")\n"; + return code; +} + +export const display_matrix_extern_scroll_string = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".scroll(" + data + ")\n"; + return code; +} + +export const display_matrix_extern_scroll_string_delay = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var code = v + ".scroll(" + data + ', speed=' + time + ', space=' + space + ")\n"; + return code; +} + +export const display_matrix_extern_clear = function (block, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.fill(0)\n' + v + '.show()\n'; + return code; +} + +export const display_matrix_extern_shift = function (a, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var op = a.getFieldValue("OP"); + var value = generator.valueToCode(a, 'val', generator.ORDER_ATOMIC); + var code = v + '.' + op + '(' + value + ')\n'; + return code; +} + +export const display_matrix_extern_get_pixel = function (block, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var value_x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var value_y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var code = v + '.pixel(int(' + value_x + '), int(' + value_y + '))'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_matrix_extern_bright_point = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = v + '.pixel(int(' + x + '), int(' + y + '), ' + dropdown_stat + ")\n" + v + '.show()\n'; + return code; +} + +export const display_matrix_extern_get_screen_pixel = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.get_brightness()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_matrix_extern_bright_screen = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var code = v + '.set_brightness(' + x + ')\n'; + return code; +} + +export const display_matrix_extern_image_builtins = function (block, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var dropdown_image = block.getFieldValue('image'); + var code = v + '.' + dropdown_image; + return [code, generator.ORDER_ATOMIC]; +} + +export const matrix_extern_image_arithmetic = function (a, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var op = a.getFieldValue("OP"); + var imga = generator.valueToCode(a, 'A', generator.ORDER_ATOMIC); + var imgb = generator.valueToCode(a, 'B', generator.ORDER_ATOMIC); + var code = v + '.map_' + op + '(' + imga + ', ' + imgb + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const matrix_extern_image_invert = function (a, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var imga = generator.valueToCode(a, 'A', generator.ORDER_ATOMIC); + var code = v + '.map_invert(' + imga + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +//oled +export const display_use_i2c_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var i2csub = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC); + var column = generator.valueToCode(this, 'column', generator.ORDER_ATOMIC); + var code = sub + " = ssd1306.SSD1306_I2C(" + row + ", " + column + ", " + i2csub + ")\n"; + return code; +} + +export const display_draw_4strings = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var value_text_line1 = generator.valueToCode(this, 'Text_line1', generator.ORDER_ASSIGNMENT) || '\'\''; + var value_text_line2 = generator.valueToCode(this, 'Text_line2', generator.ORDER_ASSIGNMENT) || '\'\''; + var value_text_line3 = generator.valueToCode(this, 'Text_line3', generator.ORDER_ASSIGNMENT) || '\'\''; + var value_text_line4 = generator.valueToCode(this, 'Text_line4', generator.ORDER_ASSIGNMENT) || '\'\''; + var code = varName + '.show_str(' + value_text_line1 + ', ' + value_text_line2 + ', ' + value_text_line3 + ', ' + value_text_line4 + ')\n' + return code; +} + +export const display_line_arbitrarily = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x1 = generator.valueToCode(this, 'x1', generator.ORDER_ATOMIC); + var location_y1 = generator.valueToCode(this, 'y1', generator.ORDER_ATOMIC); + var location_x2 = generator.valueToCode(this, 'x2', generator.ORDER_ATOMIC); + var location_y2 = generator.valueToCode(this, 'y2', generator.ORDER_ATOMIC); + var code = varName + '.show_line(' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', 1)\n'; + return code; +} + +export const display_rect = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var value_width = generator.valueToCode(this, 'width', generator.ORDER_ATOMIC); + var value_height = generator.valueToCode(this, 'height', generator.ORDER_ATOMIC); + var checkbox_fill = this.getFieldValue("fill") == 'TRUE' ? 'True' : 'False'; + var size = this.getFieldValue('OP'); + switch (checkbox_fill) { + case "True": + var code = varName + '.show_fill_rect(' + location_x + ', ' + location_y + ', ' + value_width + ', ' + value_height + ', ' + size + ')\n'; + return code; + case "False": + var code = varName + '.show_rect(' + location_x + ', ' + location_y + ', ' + value_width + ', ' + value_height + ', ' + size + ')\n'; + return code; + } +} + + +export const display_line = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var value_length = generator.valueToCode(this, 'length', generator.ORDER_ATOMIC); + var value_direction = this.getFieldValue("direction"); + var code = varName + '.show_' + value_direction + '(' + location_x + ', ' + location_y + ', ' + value_length + ', 1)\n'; + return code; +} + +export const display_onoff = function (_, generator) { + var code = (this.getFieldValue('ONOFF') == 'ON') ? '1' : '0'; + return [code, generator.ORDER_ATOMIC]; +} + +export const image_shift = function (a, generator) { + generator.definitions_['import_matrix'] = 'import matrix'; + var op = a.getFieldValue("OP"); + var image = generator.valueToCode(a, 'img', generator.ORDER_ATOMIC); + var value = generator.valueToCode(a, 'val', generator.ORDER_ATOMIC); + var code = image + '.shift_' + op + '(' + value + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_fill = function (_, generator) { + var varName = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var code = varName + '.show_fill(' + key + ')\n'; + return code; +} + +// export const switch = function (_, generator) { +// var code = this.getFieldValue('flag'); +// return [code, generator.ORDER_ATOMIC]; +// }; + +export const display_animate = function (_, generator) { + // Boolean values true and false. + var name = this.getFieldValue("ANIMATION"); + var code = 'matrix.Image.' + name; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_circle = function (_, generator) { + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var location_x = generator.valueToCode(this, 'x', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'y', generator.ORDER_ATOMIC); + var value_r = generator.valueToCode(this, 'r', generator.ORDER_ATOMIC); + var checkbox_fill = this.getFieldValue("fill") == 'TRUE' ? 'True' : 'False'; + var size = this.getFieldValue('OP'); + switch (checkbox_fill) { + case "True": + var code = varName + '.show_fill_circle(' + location_x + ', ' + location_y + ', ' + value_r + ', ' + size + ')\n'; + return code; + case "False": + var code = varName + '.show_circle(' + location_x + ', ' + location_y + ', ' + value_r + ', ' + size + ')\n'; + return code; + } +} + +export const display_triangle = function (_, generator) { + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var location_x0 = generator.valueToCode(this, 'x0', generator.ORDER_ATOMIC); + var location_y0 = generator.valueToCode(this, 'y0', generator.ORDER_ATOMIC); + var location_x1 = generator.valueToCode(this, 'x1', generator.ORDER_ATOMIC); + var location_y1 = generator.valueToCode(this, 'y1', generator.ORDER_ATOMIC); + var location_x2 = generator.valueToCode(this, 'x2', generator.ORDER_ATOMIC); + var location_y2 = generator.valueToCode(this, 'y2', generator.ORDER_ATOMIC); + var checkbox_fill = this.getFieldValue("fill") == 'TRUE' ? 'True' : 'False'; + var size = this.getFieldValue('OP'); + switch (checkbox_fill) { + case "True": + var code = varName + '.show_fill_triangle(' + location_x0 + ', ' + location_y0 + ', ' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', ' + size + ')\n'; + return code; + case "False": + var code = varName + '.show_triangle(' + location_x0 + ', ' + location_y0 + ', ' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', ' + size + ')\n'; + return code; + } +} + +export const display_oled_showBitmap = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'START_X', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'START_Y', generator.ORDER_ATOMIC); + var bmp = generator.valueToCode(this, 'bitmap_name', generator.ORDER_ATOMIC); + var w = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC); + var h = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC); + var code = varName + '.show_bitmap(' + location_x + ', ' + location_y + ', ' + bmp + ',' + w + ',' + h + ')\n'; + return code; +} + +export const display_oled_drawPixel = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_ssd1306'] = 'import ssd1306'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var location_x = generator.valueToCode(this, 'POS_X', generator.ORDER_ATOMIC); + var location_y = generator.valueToCode(this, 'POS_Y', generator.ORDER_ATOMIC); + var code = varName + '.show_pixel(' + location_x + ', ' + location_y + ')\n'; + return code; +} + +//tm1650 +export const display_tm_use_i2c_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var clk = generator.valueToCode(this, 'CLK', generator.ORDER_ATOMIC); + var dio = generator.valueToCode(this, 'DIO', generator.ORDER_ATOMIC); + // var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue("key"); + var code; + if (key == 'TM1650') { + generator.definitions_['import_tm1650'] = 'import tm1650'; + code = v + ' = tm1650.' + key + '(clk='+ clk +',dio='+ dio +')\n'; + } else if (key == 'TM1637') { + generator.definitions_['import_tm1637'] = 'import tm1637'; + code = v + ' = tm1637.' + key + '(clk='+ clk +',dio='+ dio +')\n'; + } + return code; +} + +export const display_tm1650_power = function (_, generator) { + // var type = this.getFieldValue("TYPE"); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var stat = this.getFieldValue("STAT"); + var code = v + '.' + stat + "()\n"; + return code; +} + +export const display_tm1650_show_num = function (_, generator) { + // var type = this.getFieldValue("TYPE"); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var val = generator.valueToCode(this, 'VALUE', generator.ORDER_ATOMIC); + var code = v + ".shownum(" + val + ")\n"; + return code; +} + +export const display_tm1650_show_dot = function (_, generator) { + // var type = this.getFieldValue("TYPE"); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var n = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + var stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = v + '.showDP(' + n + ", " + stat + ")\n"; + return code; +} + +export const display_tm1650_set_brightness = function (_, generator) { + // var type = this.getFieldValue("TYPE"); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var val = generator.valueToCode(this, 'VALUE', generator.ORDER_ATOMIC); + var code = v + ".intensity(" + val + ")\n"; + return code; +} + +export const tft_use_spi_init = function (_, generator) { + generator.definitions_['import_st7789'] = 'import st7789'; + var version = Boards.getSelectedBoardKey().split(':')[2] + var font = ''; + if (['mpython', 'mixgo_pe', 'mixgo_nova'].indexOf(version) >= 0) { + font = '0x700000' + } else if (['mixgo_sant'].indexOf(version) >= 0) { + font = '0xE00000' + } else { + font = '0x3A0000' + } + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sv = generator.valueToCode(this, 'SPISUB', generator.ORDER_ATOMIC); + var pv = generator.valueToCode(this, 'PINCS', generator.ORDER_ATOMIC); + var dv = generator.valueToCode(this, 'PINDC', generator.ORDER_ATOMIC); + var w = generator.valueToCode(this, 'WIDTH', generator.ORDER_ATOMIC); + var h = generator.valueToCode(this, 'HEIGHT', generator.ORDER_ATOMIC); + var op = this.getFieldValue('rotate'); + var code = v + ' = st7789.ST7789(' + sv + ', ' + w + ', ' + h + ', dc_pin=' + dv + ', cs_pin=' + pv + ', rotation=' + op + ', font_address=' + font + ')\n'; + return code; +} + +export const tft_show_image_xy = function (_, generator) { + generator.definitions_['import_st7789'] = 'import st7789'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = v + ".image(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', color=' + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = v + ".image(" + data + ', x= ' + x + ',y=' + y + ', size=' + size + ', color=0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const display_color_seclet = function (_, generator) { + var colour = this.getFieldValue('COLOR'); + var code = '0x' + colour.slice(1) + '' + var rgb565 = (code & 0xf80000) >> 8 | (code & 0xfc00) >> 5 | (code & 0xff) >> 3 + return ['0x' + rgb565.toString(16), generator.ORDER_ATOMIC]; +} + +export const tft_show_image_or_string_delay = function (_, generator) { + generator.definitions_['import_st7789'] = 'import st7789'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var op = this.getFieldValue('center'); + if (color.slice(0, 2) == "0x") { + var code = v + ".shows(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', space=' + space + ', center=' + op + ', color=' + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = v + ".shows(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', space=' + space + ', center=' + op + ', color=0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const tft_show_frame_string_delay = function (_, generator) { + generator.definitions_['import_st7789'] = 'import st7789'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = v + ".frame(" + data + ', size=' + size + ', delay=' + time + ', color=' + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = v + ".frame(" + data + ', size=' + size + ', delay=' + time + ', color=0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const tft_scroll_string_delay = function (_, generator) { + generator.definitions_['import_st7789'] = 'import st7789'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = v + ".scroll(" + data + ', y=' + y + ', size=' + size + ', speed=' + time + ', space=' + space + ', color=' + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = v + ".scroll(" + data + ', y=' + y + ', size=' + size + ', speed=' + time + ', space=' + space + ', color=0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const tft_fill = function (_, generator) { + generator.definitions_['import_st7789'] = 'import st7789'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = v + '.fill(st7789.' + key + ')\n'; + return code; +} + +export const tft_line_arbitrarily = function (_, generator) { + generator.definitions_['import_st7789'] = 'import st7789'; + var varName = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var location_x1 = generator.valueToCode(this, 'x1', generator.ORDER_ATOMIC); + var location_y1 = generator.valueToCode(this, 'y1', generator.ORDER_ATOMIC); + var location_x2 = generator.valueToCode(this, 'x2', generator.ORDER_ATOMIC); + var location_y2 = generator.valueToCode(this, 'y2', generator.ORDER_ATOMIC); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = varName + '.line(' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', color=' + color + ')\n'; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = varName + '.line(' + location_x1 + ', ' + location_y1 + ', ' + location_x2 + ', ' + location_y2 + ', color=0x' + rgb565.toString(16) + ')\n'; + } + return code; +} + +export const display_lcd_use_i2c_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue("key"); + var addr = generator.valueToCode(this, 'ADDR', generator.ORDER_ATOMIC); + var code; + generator.definitions_['import_i2clcd'] = 'import i2clcd'; + code = v + ' = i2clcd.LCD' + "(" + iv + ', lcd_width=' + key + ', i2c_addr=' + addr + ')\n'; + return code; +} + +export const lcd_show_image_or_string_delay = function (_, generator) { + generator.definitions_['import_i2clcd'] = 'import i2clcd'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var op = this.getFieldValue('center'); + var code = v + ".shows(" + data + ', column=' + x + ', line=' + y + ',center = ' + op + ")\n"; + return code; +} + +export const lcd_print_string = function (_, generator) { + generator.definitions_['import_i2clcd'] = 'import i2clcd'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var delay = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var code = v + ".print(" + data + ', column=' + x + ', line=' + y + ', delay=' + delay + ")\n"; + return code; +} + +export const lcd_backlight = function (_, generator) { + generator.definitions_['import_i2clcd'] = 'import i2clcd'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = v + '.backlight(' + key + ')\n'; + return code; +} + +export const lcd_clear = function (block, generator) { + generator.definitions_['import_i2clcd'] = 'import i2clcd'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.clear()\n'; + return code; +} + +export const display_oled_use_i2c_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var addr = generator.valueToCode(this, 'ADDR', generator.ORDER_ATOMIC); + var m = this.getFieldValue("driver"); + var version = Boards.getSelectedBoardKey().split(':')[2] + var font = ''; + if (['mpython', 'mixgo_pe', 'mixgo_nova'].indexOf(version) >= 0) { + font = '0x700000' + } else if (['mixgo_sant'].indexOf(version) >= 0) { + font = '0xE00000' + } else { + font = '0x3A0000' + } + var code; + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + code = v + ' = oled128x64.OLED' + "(" + iv + ', address=' + addr + ', font_address=' + font + ', types=' + m + ')\n'; + + return code; +} + +export const extern_oled_show_image = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".image(" + data + ")\n"; + return code; +} + +export const extern_oled_show_image_xy = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var code = v + ".image(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ")\n"; + return code; +} + +export const extern_oled_show_string = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".shows(" + data + ")\n"; + return code; +} + +export const extern_oled_show_image_or_string_delay = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var op = this.getFieldValue('center'); + var code = v + ".shows(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', space=' + space + ', center=' + op + ")\n"; + return code; +} + +export const extern_oled_show_frame_string = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".frame(" + data + ")\n"; + return code; +} + +export const extern_oled_show_frame_string_delay = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var code = v + ".frame(" + data + ', size=' + size + ', delay=' + time + ")\n"; + return code; +} + +export const extern_oled_scroll_string = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = v + ".scroll(" + data + ")\n"; + return code; +} + +export const extern_oled_scroll_string_delay = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var code = v + ".scroll(" + data + ', y=' + y + ', size=' + size + ', speed=' + time + ', space=' + space + ")\n"; + return code; +} + +export const extern_oled_clear = function (block, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.fill(0)\n' + v + '.show()\n'; + return code; +} + +export const extern_oled_shift = function (a, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var op = a.getFieldValue("OP"); + var value = generator.valueToCode(a, 'val', generator.ORDER_ATOMIC); + var code = v + '.' + op + '(' + value + ')\n'; + return code; +} + +export const extern_oled_get_pixel = function (block, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var value_x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var value_y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var code = v + '.pixel(int(' + value_x + '), int(' + value_y + '))'; + return [code, generator.ORDER_ATOMIC]; +} + +export const extern_oled_bright_point = function (_, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = v + '.pixel(int(' + x + '), int(' + y + '), ' + dropdown_stat + ")\n" + v + '.show()\n'; + return code; +} + +export const extern_oled_shape_rect = function (block, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var w = generator.valueToCode(block, 'w', generator.ORDER_ATOMIC); + var h = generator.valueToCode(block, 'h', generator.ORDER_ATOMIC); + var state = block.getFieldValue('state'); + var shape = block.getFieldValue('shape'); + var code = v + '.' + shape + '(' + x + ', ' + y + ', ' + w + ', ' + h + ', ' + state + ')\n' + v + '.show()\n'; + return code; +} + +export const extern_oled_hvline = function (block, generator) { //水平线 + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var var_length = generator.valueToCode(block, 'length', generator.ORDER_ATOMIC); + var state = block.getFieldValue('state'); + var hv = block.getFieldValue('dir_h_v'); + var code = v + '.' + (('0' == hv) ? 'v' : 'h') + 'line(' + x + ', ' + y + ', ' + var_length + ', ' + state + ')\n' + v + '.show()\n'; + return code; +} + +export const extern_oled_line = function (block, generator) { + generator.definitions_['import_oled128x64'] = 'import oled128x64'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var x1 = generator.valueToCode(block, 'x1', generator.ORDER_ATOMIC); + var y1 = generator.valueToCode(block, 'y1', generator.ORDER_ATOMIC); + var x2 = generator.valueToCode(block, 'x2', generator.ORDER_ATOMIC); + var y2 = generator.valueToCode(block, 'y2', generator.ORDER_ATOMIC); + var state = block.getFieldValue('state'); + var code = v + '.line(' + x1 + ', ' + y1 + ', ' + x2 + ', ' + y2 + ', ' + state + ')\n' + v + '.show()\n'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/display_onboard.js b/mixly/boards/default_src/micropython/generators/display_onboard.js new file mode 100644 index 00000000..476e5254 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/display_onboard.js @@ -0,0 +1,1245 @@ +import { Boards, JSFuncs } from 'mixly'; + +export const display_show_image = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + var code = "onboard_tft.image(" + data + ", color=0xffff,sync="+ s +")\n"; + } else { + if (version == "educore") { + generator.definitions_['import_' + version + '_oled'] = "from " + version + " import oled"; + var code = "oled.print(" + data + ")\n"; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = "onboard_matrix.shows(" + data + ")\n"; + } + } + return code; +} + +export const display_show_image_or_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var op = this.getFieldValue('center'); + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + var code = "onboard_tft.shows(" + data + ", space=" + space + ', center=' + op + ",sync="+ s +")\n"; + return code; + } else if (version == "educore") { + generator.definitions_['import_' + version + '_oled'] = "from " + version + " import oled"; + var code = "oled.print(" + data + ', space=' + space + ', center=' + op + ")\n"; + } + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = "onboard_matrix.shows(" + data + ', space=' + space + ', center=' + op + ")\n"; + return code; +} + +export const display_show_frame_string = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + if (version == 'mpython' || version == 'educore') { + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var code = "onboard_oled.frame(" + data + ")\n"; + } else if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "onboard_tft.frame(" + data + ", color=0xffff)\n"; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = "onboard_matrix.frame(" + data + ")\n"; + } + return code; +} + +export const display_show_frame_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + if (version == 'mpython' || version == 'educore') { + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "onboard_oled.frame(" + data + ', delay=' + time + ")\n"; + } else if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var code = "onboard_tft.frame(" + data + ', size=5 , delay=' + time + ', color=0xffff)\n'; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = "onboard_matrix.frame(" + data + ', delay=' + time + ")\n"; + } + return code; +} + +export const display_scroll_string = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mpython' || version == 'educore') { + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "onboard_oled.scroll(" + data + ")\n"; + } else if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "onboard_tft.scroll(" + data + ", color=0xffff)\n"; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "onboard_matrix.scroll(" + data + ")\n"; + } + return code; +} + +export const display_scroll_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + if (version == 'mpython' || version == 'educore') { + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var code = "onboard_oled.scroll(" + data + ', speed=' + time + ', space=' + space + ")\n"; + } else if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var code = "onboard_tft.scroll(" + data + ', y=0, size=5, speed=' + time + ', space=' + space + ', color=0xffff)\n'; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = "onboard_matrix.scroll(" + data + ', speed=' + time + ', space=' + space + ")\n"; + } + return code; +} + +export const display_scroll_way = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var way = this.getFieldValue('way'); + var code = "onboard_matrix.scroll_way(" + way + ")\n"; + return code; +} + +export const onboard_tft_scroll_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = "onboard_tft.scroll(" + data + ', y=' + y + ', size=' + size + ', speed=' + time + ', space=' + space + ', color=' + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = "onboard_tft.scroll(" + data + ', y=' + y + ', size=' + size + ', speed=' + time + ', space=' + space + ', color=0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const display_image_builtins = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var dropdown_image = block.getFieldValue('image'); + var code = 'onboard_matrix.' + dropdown_image; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_image_builtins_all = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + const PIN_VALUE = block.getFieldValue('image'); + const data = PIN_VALUE.split('.'); + if (data.length !== 2) { + throw Error('pin value error'); + } + generator.definitions_[`import_${data[0]}_${data[1]}`] = `from ${data[0]} import ${data[1]}`; + var code = data[1]; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var dropdown_image = block.getFieldValue('image'); + var code = 'onboard_matrix.' + dropdown_image; + } + return [code, generator.ORDER_ATOMIC]; +} + +/** + * @deprecated To be removed in the future + */ +export const display_image_create = function (block, generator) { + var colours = { + "#000000": "0", + //"#440000": "1", + //"#660000": "2", + //"#880000": "3", + //"#aa0000": "4", + //"#bb0000": "5", + //"#cc0000": "6", + //"#dd0000": "7", + //"#ee0000": "8", + "#ff0000": "1" + } + function pad(num) { + let newNum = ''; + if (num.length % 2 === 1) { + num = '0' + num; + } + if (num.length < 8) { + let k = 8 - num.length + for (let i = 1; i <= k; i++) { + num = '0' + num; + } + } + + for (let i = 1; i <= num.length; i++) + if (i % 2 === 0 && i !== num.length) + newNum = newNum + num[i - 1] + ',0x'; + else + newNum += num[i - 1]; + return '0x' + newNum; + } + let colorList = []; + for (let i = 0; i < 12; i++) { + let colorRow = ''; + let colorNum = 0; + let correct = 0; + + for (let j = 0; j < 32; j++) { + if (j < 8) { + correct = 7 - j + } + else if (j < 16) { + correct = 23 - j + } + else if (j < 24) { + correct = 39 - j + } + else if (j < 32) { + correct = 55 - j + } + colorNum += Number(colours[block.getFieldValue(i + '-' + j)]) * Math.pow(2, 31 - correct); + } + colorRow += pad(colorNum.toString(16)); + colorList.unshift(colorRow); + } + let codelist = []; + for (let i = 0; i < colorList.length; i++) { + codelist[i] = colorList[colorList.length - 1 - i]; + } + //var code = "bytearray(b'" + colorList.join('') + "')"; + var code = '[' + codelist + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_bitmap_create = function (block, generator) { + const BITMAP = block.getFieldValue('BITMAP'); + const data = []; + for (let i = 0; i < 12; i++) { + for (let j = 0; j < 4; j++) { + let temp = 0; + let str = ''; + for (let k = 0; k < 8; k++) { + if (!BITMAP[i][j * 8 + k]) { + continue; + } + temp |= BITMAP[i][j * 8 + k] << k; + } + str = temp.toString(16); + if (str.length == 1) { + str = '0' + str; + } + data.push('0x' + str); + } + } + return [`[${data.join(',')}]`, generator.ORDER_ATOMIC]; +} + +export const display_clear = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mpython') { + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var code = 'onboard_oled.fill(0)\n' + 'onboard_oled.show()\n'; + } else if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + var code = 'onboard_tft.fill(0,sync='+s+')\n'; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = 'onboard_matrix.fill(0)\n' + 'onboard_matrix.show()\n'; + } + return code; +} + +export const display_available = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var code = 'onboard_tft.write()\n'; + return code; +} + +export const image_arithmetic = function (a, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var op = a.getFieldValue("OP"); + var imga = generator.valueToCode(a, 'A', generator.ORDER_ATOMIC); + var imgb = generator.valueToCode(a, 'B', generator.ORDER_ATOMIC); + var code = 'onboard_matrix.map_' + op + '(' + imga + ', ' + imgb + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const image_invert = function (a, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var imga = generator.valueToCode(a, 'A', generator.ORDER_ATOMIC); + var code = 'onboard_matrix.map_invert(' + imga + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const display_shift = function (a, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mpython') { + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var op = a.getFieldValue("OP"); + var value = generator.valueToCode(a, 'val', generator.ORDER_ATOMIC); + var code = 'onboard_oled.' + op + '(' + value + ')\n'; + } else if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var op = a.getFieldValue("OP"); + var value = generator.valueToCode(a, 'val', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + var code = 'onboard_tft.' + op + '(' + value + ',sync='+ s +')\n'; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var op = a.getFieldValue("OP"); + var value = generator.valueToCode(a, 'val', generator.ORDER_ATOMIC); + var code = 'onboard_matrix.' + op + '(' + value + ')\n'; + } + return code; +} + +// export const onboard_oled_shift = function (a) { +// var version = Boards.getSelectedBoardKey().split(':')[2] + +// return code; +// }; + +export const display_get_pixel = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mpython') { + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var value_x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var value_y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var code = 'onboard_oled.pixel(int(' + value_x + '), int(' + value_y + '))'; + } else if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var value_x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var value_y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var code = 'onboard_tft.pixel(int(' + value_x + '), int(' + value_y + '))'; + } + else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var value_x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var value_y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var code = 'onboard_matrix.pixel(int(' + value_x + '), int(' + value_y + '))'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const display_bright_point = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var code = 'onboard_tft.pixel(int(' + x + '), int(' + y + '), 0xffff)\n'; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = 'onboard_matrix.pixel(int(' + x + '), int(' + y + '), ' + dropdown_stat + ")\n" + 'onboard_matrix.show()\n'; + } + return code; +} + +export const display_get_screen_pixel = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var code = 'onboard_tft.get_brightness()'; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = 'onboard_matrix.get_brightness()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const display_bright_screen = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())) { + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var code = 'onboard_tft.set_brightness(' + x + ')\n'; + } else { + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var code = 'onboard_matrix.set_brightness(' + x + ')\n'; + } + return code; +} + +/** + * @deprecated To be removed in the future + */ +export const mixgome_display_image_create = function (block, generator) { + var colours = { + "#000000": "0", + "#ff0000": "1" + } + function pad(num) { + let newNum = ''; + if (num.length % 2 === 1) { + num = '0' + num; + } + + for (let i = 1; i <= num.length; i++) + if (i % 2 === 0 && i !== num.length) + newNum = newNum + num[i - 1] + '\\x'; + else + newNum += num[i - 1]; + return '\\x' + newNum; + } + let colorList = []; + for (let i = 0; i < 5; i++) { + let colorRow = ''; + let colorNum = 0; + for (let j = 0; j < 8; j++) { + colorNum += Number(colours[block.getFieldValue((4 - i) + '-' + j)]) * Math.pow(2, j); + } + colorRow += pad(colorNum.toString(16)); + colorList.unshift(colorRow); + } + + var code = "bytearray(b'" + colorList.join('') + "')"; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixgome_display_bitmap_create = function (block, generator) { + const BITMAP = block.getFieldValue('BITMAP'); + const data = []; + for (let i = 0; i < 5; i++) { + let temp = 0; + let str = ''; + for (let k = 0; k < 8; k++) { + if (!BITMAP[i][k]) { + continue; + } + temp |= BITMAP[i][k] << k; + } + str = temp.toString(16); + if (str.length == 1) { + str = '0' + str; + } + data.push('\\x' + str); + } + return [`bytearray(b'${data.join('')}')`, generator.ORDER_ATOMIC]; +} + +/** + * @deprecated To be removed in the future + */ +export const mixgomini_display_image_create = function (block, generator) { + var blinkColor = '#ff0000'; + var code = ''; + for (let i = 0; i < 12; i++) { + let value = 0; + for (let j = 0; j < 8; j++) { + if (block.getFieldValue(`${j}-${i}`) !== blinkColor) { + continue; + } + value += 1 << j; + } + let temp = value.toString(16); + code += '\\x' + Array(2 - temp.length).fill(0).join('') + temp; + } + code = `bytearray(b'${code}')`; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixgomini_display_bitmap_create = function (block, generator) { + const BITMAP = block.getFieldValue('BITMAP'); + const data = []; + for (let i = 0; i < 12; i++) { + let temp = 0; + let str = ''; + for (let k = 0; k < 8; k++) { + if (!BITMAP[k][i]) { + continue; + } + temp |= BITMAP[k][i] << k; + } + str = temp.toString(16); + if (str.length == 1) { + str = '0' + str; + } + data.push('\\x' + str); + } + return [`bytearray(b'${data.join('')}')`, generator.ORDER_ATOMIC]; +} + +export const mixgome_display_font = function (a, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var op = a.getFieldValue("OP"); + var code = 'onboard_matrix.font(' + op + ')\n'; + return code; +} + +/** + * @deprecated To be removed in the future + */ +export const mixgo_display_image_create_new = function (block, generator) { + var colours = { + "#000000": "0", + "#ff0000": "1" + } + function pad(num) { + let newNum = ''; + if (num.length % 2 === 1) { + num = '0' + num; + } + while (num.length < 4) { + num = '0' + num; + } + for (let i = 1; i <= num.length; i++) + if (i % 2 === 0 && i !== num.length) + newNum = newNum + num[i - 1] + '\\x'; + else + newNum += num[i - 1]; + return '\\x' + newNum; + } + let colorList = []; + for (let i = 0; i < 8; i++) { + let colorRow = ''; + let colorNum = 0; + for (let j = 0; j < 16; j++) { + var c = (j + 8) % 16 + colorNum += Number(colours[block.getFieldValue((7 - i) + '-' + c)]) * Math.pow(2, j); + } + colorRow += pad(colorNum.toString(16)); + colorList.unshift(colorRow); + } + + var code = "bytearray(b'" + colorList.join('') + "')"; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixgo_display_bitmap_create = function (block, generator) { + const BITMAP = block.getFieldValue('BITMAP'); + const data = []; + for (let i = 0; i < 8; i++) { + for (let j = 0; j < 2; j++) { + let temp = 0; + let str = ''; + for (let k = 0; k < 8; k++) { + if (!BITMAP[i][j * 8 + k]) { + continue; + } + temp |= BITMAP[i][j * 8 + k] << k; + } + str = temp.toString(16); + if (str.length == 1) { + str = '0' + str; + } + data.push('\\x' + str); + } + } + return [`bytearray(b'${data.join('')}')`, generator.ORDER_ATOMIC]; +} + +//mpython +export const mpython_pbm_image = function (_, generator) { + const PIN_VALUE = this.getFieldValue('path'); + const data = PIN_VALUE.split('.'); + if (data.length !== 2) { + throw Error('pin value error'); + } + generator.definitions_[`import_${data[0]}_${data[1]}`] = `from ${data[0]} import ${data[1]}`; + return [data[1], generator.ORDER_ATOMIC]; +} + +export const onboard_oled_show_image = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "onboard_oled.image(" + data + ")\n"; + return code; +} + +export const onboard_oled_show_image_xy = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var code = "onboard_oled.image(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ")\n"; + return code; +} + +export const onboard_oled_show_string = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var code = "onboard_oled.shows(" + data + ")\n"; + return code; +} + +export const onboard_oled_show_image_or_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var op = this.getFieldValue('center'); + var code = "onboard_oled.shows(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', space=' + space + ', center=' + op + ")\n"; + return code; +} + +export const onboard_oled_show_frame_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var code = "onboard_oled.frame(" + data + ', size=' + size + ', delay=' + time + ")\n"; + return code; +} + +export const onboard_oled_scroll_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var code = "onboard_oled.scroll(" + data + ', y=' + y + ', size=' + size + ', speed=' + time + ', space=' + space + ")\n"; + return code; +} + +export const onboard_oled_bright_point = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = 'onboard_oled.pixel(int(' + x + '), int(' + y + '), ' + dropdown_stat + ")\n" + 'onboard_oled.show()\n'; + return code; +} + +export const mpython_display_shape_rect = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var w = generator.valueToCode(block, 'w', generator.ORDER_ATOMIC); + var h = generator.valueToCode(block, 'h', generator.ORDER_ATOMIC); + var state = block.getFieldValue('state'); + var shape = block.getFieldValue('shape'); + var code = 'onboard_oled.' + shape + '(' + x + ', ' + y + ', ' + w + ', ' + h + ', ' + state + ')\n' + 'onboard_oled.show()\n'; + return code; +} + +export const mpython_display_hvline = function (block, generator) { //水平线 + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var var_length = generator.valueToCode(block, 'length', generator.ORDER_ATOMIC); + var state = block.getFieldValue('state'); + var hv = block.getFieldValue('dir_h_v'); + var code = 'onboard_oled.' + (('0' == hv) ? 'v' : 'h') + 'line(' + x + ', ' + y + ', ' + var_length + ', ' + state + ')\n' + 'onboard_oled.show()\n'; + return code; +} + +export const mpython_display_line = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_oled'] = "from " + version + " import onboard_oled"; + var x1 = generator.valueToCode(block, 'x1', generator.ORDER_ATOMIC); + var y1 = generator.valueToCode(block, 'y1', generator.ORDER_ATOMIC); + var x2 = generator.valueToCode(block, 'x2', generator.ORDER_ATOMIC); + var y2 = generator.valueToCode(block, 'y2', generator.ORDER_ATOMIC); + var state = block.getFieldValue('state'); + var code = 'onboard_oled.line(' + x1 + ', ' + y1 + ', ' + x2 + ', ' + y2 + ', ' + state + ')\n' + 'onboard_oled.show()\n'; + return code; +} + +/** + * @deprecated To be removed in the future + */ +export const mixbot_display_image_create = function (block, generator) { + var colours = { + "#000000": "0", + "#ff0000": "1" + } + function pad(num) { + let newNum = ''; + if (num.length % 2 === 1) { + num = '0' + num; + } + + for (let i = 1; i <= num.length; i++) + if (i % 2 === 0 && i !== num.length) + newNum = newNum + num[i - 1] + '\\x'; + else + newNum += num[i - 1]; + return '\\x' + newNum; + } + let colorList = []; + for (let i = 0; i < 5; i++) { + let colorRow = ''; + let colorNum = 0; + for (let j = 0; j < 5; j++) { + colorNum += Number(colours[block.getFieldValue((4 - i) + '-' + j)]) * Math.pow(2, j); + } + colorRow += pad(colorNum.toString(16)); + colorList.unshift(colorRow); + } + + var code = "b'" + colorList.join('') + "'"; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixbot_display_bitmap_create = function (block, generator) { + const BITMAP = block.getFieldValue('BITMAP'); + const data = []; + for (let i = 0; i < 5; i++) { + let temp = 0; + let str = ''; + for (let k = 0; k < 5; k++) { + if (!BITMAP[i][k]) { + continue; + } + temp |= BITMAP[i][k] << k; + } + str = temp.toString(16); + if (str.length == 1) { + str = '0' + str; + } + data.push('\\x' + str); + } + return [`bytearray(b'${data.join('')}')`, generator.ORDER_ATOMIC]; +} + +export const mixbot_display_get_screen_pixel = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = 'onboard_matrix.screenbright()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixbot_display_get_ambientbright = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var code = 'onboard_matrix.ambientbright()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixbot_display_bright_screen = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var code = 'onboard_matrix.screenbright(' + x + ')\n'; + return code; +} + +export const mixbot_display_rotate = function (a, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var op = a.getFieldValue("OP"); + var code = 'onboard_matrix.direction(' + op + ')\n'; + return code; +} + +/** + * @deprecated To be removed in the future + */ +export const bitbot_display_image_create = function (block, generator) { + var colours = { + "#000000": "0", + "#ff0000": "1" + } + function pad(num) { + + if (num.length == 1) { + return '\\x0' + num + '\\x00'; + } + if (num.length == 2) { + return '\\x' + num + '\\x00'; + } + if (num.length == 3) { + return '\\x' + num[1] + num[2] + '\\x0' + num[0]; + } + } + let colorList = []; + for (let i = 0; i < 12; i++) { + let colorRow = ''; + let colorNum = 0; + for (let j = 0; j < 12; j++) { + colorNum += Number(colours[block.getFieldValue((11 - i) + '-' + j)]) * Math.pow(2, j); + } + colorRow += pad(colorNum.toString(16)); + colorList.unshift(colorRow); + } + + var code = "b'" + colorList.join('') + "'"; + return [code, generator.ORDER_ATOMIC]; +} + +export const bitbot_display_bitmap_create = function (block, generator) { + const BITMAP = block.getFieldValue('BITMAP'); + const data = []; + for (let i = 0; i < 12; i++) { + let temp = 0; + let str = ''; + for (let k = 0; k < 8; k++) { + if (!BITMAP[i][k]) { + continue; + } + temp |= BITMAP[i][k] << k; + } + str = temp.toString(16); + if (str.length == 1) { + str = '0' + str; + } + data.push('\\x' + str); + temp = 0; + str = ''; + for (let k = 0; k < 4; k++) { + if (!BITMAP[i][k]) { + continue; + } + temp |= BITMAP[i][k + 8] << k; + } + str = temp.toString(16); + if (str.length == 1) { + str = '0' + str; + } + data.push('\\x' + str); + } + return [`bytearray(b'${data.join('')}')`, generator.ORDER_ATOMIC]; +} + +export const onboard_tft_show_image_xy = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = "onboard_tft.image(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', color='+ color +",sync=" + s +")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = "onboard_tft.image(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', color=0x' + rgb565.toString(16) + ",sync=" + s + ")\n"; + } + return code; +} + +export const onboard_tft_show_image_xy_direct = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ASSIGNMENT); + var code = "onboard_tft.picture(" + x + ',' + y + ',' + direct + ")\n"; + return code; +} + +export const onboard_tft_show_image_or_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var space = generator.valueToCode(this, 'space', generator.ORDER_ASSIGNMENT); + var op = this.getFieldValue('center'); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = "onboard_tft.shows(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', space=' + space + ', center=' + op + ', color=' + color + ",sync=" + s + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = "onboard_tft.shows(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', space=' + space + ', center=' + op + ', color=0x' + rgb565.toString(16) +",sync=" + s +")\n"; + } + return code; +} + +export const onboard_tft_show_frame_string_delay = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var time = generator.valueToCode(this, 'time', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = "onboard_tft.frame(" + data + ', size=' + size + ', delay=' + time + ', color=' + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = "onboard_tft.frame(" + data + ', size=' + size + ', delay=' + time + ', color=0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const onboard_tft_display_shape_rect = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var w = generator.valueToCode(block, 'w', generator.ORDER_ATOMIC); + var h = generator.valueToCode(block, 'h', generator.ORDER_ATOMIC); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var shape = block.getFieldValue('shape'); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = 'onboard_tft.' + shape + '(' + x + ', ' + y + ', ' + w + ', ' + h + ', ' + color + ',sync=' + s +')\n'; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = 'onboard_tft.' + shape + '(' + x + ', ' + y + ', ' + w + ', ' + h + ', 0x' + rgb565.toString(16) + ',sync=' + s +')\n'; + } + return code; +} + +export const onboard_tft_display_hvline = function (block, generator) { //水平线 + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var var_length = generator.valueToCode(block, 'length', generator.ORDER_ATOMIC); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var hv = block.getFieldValue('dir_h_v'); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = 'onboard_tft.' + (('0' == hv) ? 'v' : 'h') + 'line(' + x + ', ' + y + ', ' + var_length + ', ' + color + ',sync=' + s +')\n'; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = 'onboard_tft.' + (('0' == hv) ? 'v' : 'h') + 'line(' + x + ', ' + y + ', ' + var_length + ', 0x' + rgb565.toString(16) + ',sync=' + s +')\n'; + } + return code; +} + +export const onboard_tft_display_line = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x1 = generator.valueToCode(block, 'x1', generator.ORDER_ATOMIC); + var y1 = generator.valueToCode(block, 'y1', generator.ORDER_ATOMIC); + var x2 = generator.valueToCode(block, 'x2', generator.ORDER_ATOMIC); + var y2 = generator.valueToCode(block, 'y2', generator.ORDER_ATOMIC); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = 'onboard_tft.line(' + x1 + ', ' + y1 + ', ' + x2 + ', ' + y2 + ', ' + color + ',sync=' + s +')\n'; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = 'onboard_tft.line(' + x1 + ', ' + y1 + ', ' + x2 + ', ' + y2 + ', 0x' + rgb565.toString(16) + ',sync=' + s +')\n'; + } + return code; +} + +export const onboard_tft_get_pixel = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var value_x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var value_y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var code = 'onboard_tft.pixel(int(' + value_x + '), int(' + value_y + '))'; + return [code, generator.ORDER_ATOMIC]; +} + +export const onboard_tft_bright_point = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = 'onboard_tft.pixel(int(' + x + '), int(' + y + '), ' + color + ',sync='+ s + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = 'onboard_tft.pixel(int(' + x + '), int(' + y + '), 0x' + rgb565.toString(16) + ',sync='+ s + ")\n"; + } + return code; +} + +export const onboard_tft_fill = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = 'onboard_tft.fill(' + color + ',sync=' + s +')\n'; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = 'onboard_tft.fill(0x' + rgb565.toString(16) + ',sync=' + s + ')\n'; + } + return code; +} + +export const onboard_tft_clock_init = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_Clock'] = "from " + version + " import Clock"; + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = sub + "=Clock(" + x + ', ' + y + ', ' + size + ', ' + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = sub + "=Clock(" + x + ', ' + y + ', ' + size + ', 0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const onboard_tft_clock_get_rtctime = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_Clock'] = "from " + version + " import Clock"; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ASSIGNMENT); + var code = sub + ".set_rtctime()\n"; + return code; +} + +export const onboard_tft_clock_set_time = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_Clock'] = "from " + version + " import Clock"; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ASSIGNMENT); + var h = generator.valueToCode(this, 'h', generator.ORDER_ASSIGNMENT); + var m = generator.valueToCode(this, 'm', generator.ORDER_ASSIGNMENT); + var s = generator.valueToCode(this, 's', generator.ORDER_ASSIGNMENT); + var code = sub + ".set_time(" + h + ', ' + m + ', ' + s + ")\n"; + return code; +} + +export const onboard_tft_clock_draw = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_Clock'] = "from " + version + " import Clock"; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ASSIGNMENT); + var code = sub + ".draw_clock()\n"; + return code; +} + +export const onboard_tft_clock_clear = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_Clock'] = "from " + version + " import Clock"; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = sub + ".clear(" + color + ")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = sub + ".clear(0x" + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const onboard_tft_display_shape_circle = function (block, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var x = generator.valueToCode(block, 'x', generator.ORDER_ATOMIC); + var y = generator.valueToCode(block, 'y', generator.ORDER_ATOMIC); + var R = generator.valueToCode(block, 'r', generator.ORDER_ATOMIC); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var shape = block.getFieldValue('shape'); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = 'onboard_tft.ellipse(' + x + ', ' + y + ', ' + R + ', ' + R + ', ' + color + ', ' + shape + ',sync=' + s +')\n'; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = 'onboard_tft.ellipse(' + x + ', ' + y + ', ' + R + ', ' + R + ', 0x' + rgb565.toString(16) + ', ' + shape + ',sync=' + s +')\n'; + } + return code; +} + +export const draw_pointer = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + if (['Python ESP32-S3', 'Python ESP32-C5'].includes(JSFuncs.getPlatform())){ + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var angle = generator.valueToCode(this, 'angle', generator.ORDER_ASSIGNMENT); + var code = "onboard_tft.pointern(angle=" + angle + ")\n"; + }else{ + generator.definitions_['import_' + version + '_onboard_matrix'] = "from " + version + " import onboard_matrix"; + var angle = generator.valueToCode(this, 'angle', generator.ORDER_ASSIGNMENT); + var code = "onboard_matrix.pointern(angle=" + angle + ")\n"; + } + return code; +} + +export const nova_draw_pointer = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var angle = generator.valueToCode(this, 'angle', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (color.slice(0, 2) == "0x") { + var code = "onboard_tft.pointern(angle=" + angle + ", color="+ color +")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = "onboard_tft.pointern(angle=" + angle + ', color=0x' + rgb565.toString(16) + ")\n"; + } + return code; +} + +export const onboard_tft_show_texts = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + if (color.slice(0, 2) == "0x") { + var code = "onboard_tft.texts(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', color='+ color +",sync=" + s +")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = "onboard_tft.texts(" + data + ', x=' + x + ', y=' + y + ', size=' + size + ', color=0x' + rgb565.toString(16) + ",sync=" + s + ")\n"; + } + return code; +} + +export const onboard_tft_show_qrcode = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var direct = generator.valueToCode(this, 'direct', generator.ORDER_ATOMIC); + var code = 'onboard_tft.qrcode(' + direct + ')\n'; + return code; +} + +export const onboard_tft_show_qrcode_details = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_tft'] = "from " + version + " import onboard_tft"; + var data = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT); + var x = generator.valueToCode(this, 'x', generator.ORDER_ASSIGNMENT); + var y = generator.valueToCode(this, 'y', generator.ORDER_ASSIGNMENT); + var size = generator.valueToCode(this, 'size', generator.ORDER_ASSIGNMENT); + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var s = generator.valueToCode(this, 'boolean', generator.ORDER_ATOMIC) || 'True'; + var correct = this.getFieldValue('correct'); + if (color.slice(0, 2) == "0x") { + var code = "onboard_tft.qrcode(" + data + ',x=' + x + ',y=' + y + ',size=' + size + ',correct=' + correct+ ',color='+ color +",sync=" + s +")\n"; + } else { + const rgbValues = color.match(/\d+/g); + const r = parseInt(rgbValues[0]); + const g = parseInt(rgbValues[1]); + const b = parseInt(rgbValues[2]); + var rgb = "0x" + ((r << 16) + (g << 8) + b).toString(16).padStart(4, "0"); + var rgb565 = (rgb & 0xf80000) >> 8 | (rgb & 0xfc00) >> 5 | (rgb & 0xff) >> 3; + var code = "onboard_tft.qrcode(" + data + ',x=' + x + ',y=' + y + ',size=' + size + ',correct=' + correct + ',color=0x' + rgb565.toString(16) + ",sync=" + s + ")\n"; + } + return code; +} + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_show_image = display_show_image; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_show_frame_string = display_get_screen_pixel; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_shift = display_shift; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_get_screen_pixel = display_get_screen_pixel; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_bright_screen = display_bright_screen; + +/** + * @deprecated To be removed in the future + */ +export const onboard_tft_clear = display_clear; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/factory.js b/mixly/boards/default_src/micropython/generators/factory.js new file mode 100644 index 00000000..24365c5e --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/factory.js @@ -0,0 +1,95 @@ +export const factory_from_import = function (_, generator) { + var path = this.getFieldValue('path'); + var module = this.getFieldValue('module'); + generator.definitions_['import_' + path + '_' + module] = 'from ' + path + ' import ' + module; + return ''; +} + +export const factory_import = function (_, generator) { + var module = this.getFieldValue('module'); + generator.definitions_['import_' + module] = 'import ' + module; + return ''; +} + +export const factory_function_noreturn = function (_, generator) { + var NAME = this.getFieldValue('NAME'); + var code = new Array(this.itemCount_); + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || ''; + } + return NAME + '(' + code.join(', ') + ')\n'; +} + +export const factory_function_return = function (_, generator) { + var NAME = this.getFieldValue('NAME'); + var code = new Array(this.itemCount_); + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || ''; + } + return [NAME + '(' + code.join(', ') + ')', generator.ORDER_ATOMIC]; +} + +export const factory_declare = function () { + var TYPE = this.getFieldValue('TYPE'); + var NAME = this.getFieldValue('NAME'); + return NAME + ' = ' + TYPE + '()\n'; +} + +export const factory_callMethod_noreturn = function (_, generator) { + var NAME = this.getFieldValue('NAME'); + var METHOD = this.getFieldValue('METHOD'); + var code = new Array(this.itemCount_); + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || ''; + } + return NAME + '.' + METHOD + '(' + code.join(', ') + ')\n'; +} + +export const factory_callMethod_return = function (_, generator) { + var NAME = this.getFieldValue('NAME'); + var METHOD = this.getFieldValue('METHOD'); + var code = new Array(this.itemCount_); + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || ''; + } + return [NAME + '.' + METHOD + '(' + code.join(', ') + ')', generator.ORDER_ATOMIC]; +} + +export const factory_block = function () { + var VALUE = this.getFieldValue('VALUE'); + //if(!(VALUE.charAt(VALUE.length-1)==";")){ + //VALUE=VALUE+';'; + //} + return VALUE + '\n'; +} + +export const factory_block_return = function (_, generator) { + var VALUE = this.getFieldValue('VALUE'); + return [VALUE, generator.ORDER_ATOMIC]; +} + +export const factory_block_with_textarea = function () { + var VALUE = this.getFieldValue('VALUE'); + //if(!(VALUE.charAt(VALUE.length-1)==";")){ + //VALUE=VALUE+';'; + //} + return VALUE + '\n'; +} + +export const factory_block_return_with_textarea = function (_, generator) { + var VALUE = this.getFieldValue('VALUE'); + return [VALUE, generator.ORDER_ATOMIC]; +} + +export const folding_block = function (_, generator) { + var comment = this.getFieldValue('peien'); + comment = "#" + comment; + var branch = generator.statementToCode(this, 'DO'); + branch = branch.replace(/(^\s*)|(\s*$)/g, "");//去除两端空格 + branch = branch.replace(/(\n\s\s\s\s)/g, "\n");//去除换行时空格 + return comment + '\n' + branch + '\n'; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/inout.js b/mixly/boards/default_src/micropython/generators/inout.js new file mode 100644 index 00000000..7180f807 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/inout.js @@ -0,0 +1,158 @@ +import * as Blockly from 'blockly/core'; + +// ok +export const inout_highlow = function (_, generator) { + // Boolean values HIGH and LOW. + var code = (this.getFieldValue('BOOL') == 'HIGH') ? '1' : '0'; + return [code, generator.ORDER_ATOMIC]; +} + +// ok +export const inout_digital_write = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = ""; + code += dropdown_pin + '.value(' + dropdown_stat + ')\n' + return code; +} + +// ok +export const inout_digital_read = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = ""; + code = dropdown_pin + '.value()'; + return [code, generator.ORDER_ATOMIC]; +} + +// ok +export const inout_pwm_analog_write = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + //var dropdown_stat = this.getFieldValue('STAT'); + var value_num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + //generator.setups_['setup_output'+dropdown_pin] = 'pinMode('+dropdown_pin+', OUTPUT);'; + var code = dropdown_pin + '.duty_u16(' + value_num + ')\n'; + return code; +} + +// ok +export const inout_analog_write = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + //var dropdown_stat = this.getFieldValue('STAT'); + var value_num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + //generator.setups_['setup_output'+dropdown_pin] = 'pinMode('+dropdown_pin+', OUTPUT);'; + var code = dropdown_pin + '.write(' + value_num + ')\n'; + return code; +} + +// ok +export const inout_analog_write_set = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var value_num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = dropdown_pin + '.set_analog_' + key + '(' + value_num + ')\n'; + //var code = 'pin' + dropdown_pin + '.set_analog_period(' + value_num + ')\n'; + return code; +} + +export const inout_pwm_analog_write_set_freq = function (_, generator) { + //generator.definitions_['import_machine_Pin'] = "from machine import Pin"; + // generator.definitions_['import_machine_PWM'] = "from machine import PWM"; + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var value_num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var code = dropdown_pin + '.freq(' + value_num + ')\n'; + //var code = 'pin' + dropdown_pin + '.set_analog_period(' + value_num + ')\n'; + return code; +} + +// ok +export const inout_analog_read = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + //generator.setups_['setup_input_'+dropdown_pin] = 'pinMode('+dropdown_pin+', INPUT);'; + var code = dropdown_pin + '.read_u16()'; + return [code, generator.ORDER_ATOMIC]; +} + +// ok +export const inout_pin_pressed = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var pin = generator.valueToCode(this, 'pin', generator.ORDER_ATOMIC); + var code = pin + '.read()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const inout_pin_attachInterrupt = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_mode = this.getFieldValue('mode'); + var atta = generator.valueToCode(this, 'DO', generator.ORDER_ATOMIC); + var code = 'machine.Pin(' + dropdown_pin + ').irq' + '(handler=' + atta + ', trigger=' + dropdown_mode + ')\n' + //var funcName = 'attachInterrupt_func_' + dropdown_pin; + //var branch = generator.statementToCode(this, 'DO') || generator.PASS; + //var code2 = 'def' + ' ' + funcName + '(p):\n' + branch + '\n'; + //generator.setups_[funcName] = code2; + return code; +} + +export const inout_digital_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var pin_obj = this.getFieldValue('PIN_OBJ') || 'pin#'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_mode = this.getFieldValue('MODE'); + var varName = (pin_obj == 'pin#') ? 'pin' + dropdown_pin : generator.variableDB_.getName(pin_obj, Blockly.Variables.NAME_TYPE); + var code = varName + ' = machine.Pin(' + dropdown_pin + ', ' + dropdown_mode + ')\n'; + return code; +} + +export const inout_pwm_analog_write_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var pin_obj = this.getFieldValue('PIN_OBJ') || 'pwm#'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var varName = (pin_obj == 'pwm#') ? 'pwm' + dropdown_pin : generator.variableDB_.getName(pin_obj, Blockly.Variables.NAME_TYPE); + var code = varName + ' = machine.PWM(machine.Pin(' + dropdown_pin + '))\n'; + return code; +} + +// ok +export const inout_analog_write_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var pin_obj = this.getFieldValue('PIN_OBJ') || 'dac#'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var varName = (pin_obj == 'dac#') ? 'dac' + dropdown_pin : generator.variableDB_.getName(pin_obj, Blockly.Variables.NAME_TYPE); + var code = varName + ' = machine.DAC(machine.Pin(' + dropdown_pin + '))\n'; + return code; +} + +export const inout_analog_read_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var pin_obj = this.getFieldValue('PIN_OBJ') || 'adc#'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var varName = (pin_obj == 'adc#') ? 'adc' + dropdown_pin : generator.variableDB_.getName(pin_obj, Blockly.Variables.NAME_TYPE); + var code = varName + ' = machine.ADC(machine.Pin(' + dropdown_pin + '))\n'; + return code; +} + +export const inout_analog_atten = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + //var dropdown_stat = this.getFieldValue('STAT'); + var value_atten = this.getFieldValue('atten') + var code = dropdown_pin + '.atten(' + value_atten + ')\n'; + return code; +} + +// ok +export const inout_pin_pressed_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var pin_obj = this.getFieldValue('PIN_OBJ') || 'tc#'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var varName = (pin_obj == 'tc#') ? 'tc' + dropdown_pin : generator.variableDB_.getName(pin_obj, Blockly.Variables.NAME_TYPE); + var code = varName + ' = machine.TouchPad(machine.Pin(' + dropdown_pin + '))\n'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/iot.js b/mixly/boards/default_src/micropython/generators/iot.js new file mode 100644 index 00000000..11479dab --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/iot.js @@ -0,0 +1,366 @@ +export const iot_wifi_connect = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var username = generator.valueToCode(this, 'WIFINAME', generator.ORDER_ATOMIC); + var password = generator.valueToCode(this, 'PASSWORD', generator.ORDER_ATOMIC); + var code = 'mixiot.wlan_connect(' + username + ', ' + password + ')\n'; + return code; +} + +export const iot_onenet_connect = function (_, generator) { + generator.definitions_['import_onenet'] = "import onenet"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var client = generator.valueToCode(this, 'CLIENT', generator.ORDER_ATOMIC); + var server = generator.valueToCode(this, 'SERVER', generator.ORDER_ATOMIC); + var username = generator.valueToCode(this, 'USERNAME', generator.ORDER_ATOMIC); + var password = generator.valueToCode(this, 'PASSWORD', generator.ORDER_ATOMIC); + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var subscribe = generator.valueToCode(this, 'SUB', generator.ORDER_ASSIGNMENT) || 'None'; + var code = v + ' = onenet.init_MQTT_client(' + client + ', ' + server + ', ' + username + ', ' + password + ', ' + topic + ', ' + subscribe + ')\n'; + return code; +} + +export const iot_onenet_disconnect = function (_, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + generator.definitions_['import_onenet'] = "import onenet"; + var code = v + '.do_disconnect()\n'; + return code; +} + +export const iot_onenet_publish_dict = function (_, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var d = generator.valueToCode(this, 'DICT', generator.ORDER_ATOMIC); + var check = this.getFieldValue("is_print") == 'TRUE' ? 'True' : 'False'; + generator.definitions_['import_onenet'] = "import onenet"; + var code = v + '.publish(' + d + ', is_print=' + check + ')\n'; + return code; +} + +export const iot_onenet_check = function (_, generator) { + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + generator.definitions_['import_onenet'] = "import onenet"; + var code = v + '.check_msg()\n'; + return code; +} + +export const iot_onenet_publish = function (_, generator) { + // Create a list with any number of elements of any type. + + //var size=window.parseFloat(this.getFieldValue('SIZE')); + generator.definitions_['import_onenet'] = "import onenet"; + var ck = new Array(this.itemCount_); + var cv = new Array(this.itemCount_); + var ct = new Array(this.itemCount_); + + var default_value = '0'; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + + for (let n = 0; n < this.itemCount_; n++) { + var keyName = this.getFieldValue('KEY' + n); + ck[n] = keyName; + } + for (let n = 0; n < this.itemCount_; n++) { + cv[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + var code = v + ".publish({"; + for (let n = 0; n < this.itemCount_; n++) { + ct[n] = ck[n] + ': ' + cv[n]; + } + //var code = "c.publish('$dp', pubData("+ '{' + code.join(', ') + '})\n'; + //var code =''+varName+'['+size+"]"+'='+ '{' + code.join(', ') + '}\n'; + //generator.setups_['setup_lists'+varName] = code; + code = code + ct.join(', ') + "})\n"; + return code; +} + +export const iot_mixio_connect = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + generator.definitions_['import_machine'] = "import machine"; + generator.definitions_['import_ubinascii_hexlify'] = "from ubinascii import hexlify"; + var server = generator.valueToCode(this, 'SERVER', generator.ORDER_ATOMIC); + var username = generator.valueToCode(this, 'USERNAME', generator.ORDER_ATOMIC); + var password = generator.valueToCode(this, 'PASSWORD', generator.ORDER_ATOMIC); + var project = generator.valueToCode(this, 'PROJECT', generator.ORDER_ATOMIC); + //var subscribe = generator.valueToCode(this, 'SUB', generator.ORDER_ASSIGNMENT) || '0'; + var a = "'" + username.replace("'", "").replace("'", "") + "/" + project.replace("'", "").replace("'", "") + "/'" + var code = 'MQTT_USR_PRJ = ' + a + '\n' + 'mqtt_client = mixiot.init_MQTT_client(' + server + ', ' + username + ', ' + password + ', MQTT_USR_PRJ)\n'; + return code; +} + +export const IOT_MIXIO_PUBLISH = function (_, generator) { + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var msg = generator.valueToCode(this, 'MSG', generator.ORDER_ATOMIC); + generator.definitions_['import_mixiot'] = "import mixiot"; + var code = 'mqtt_client.publish(MQTT_USR_PRJ + ' + topic + ', ' + msg + ')\n'; + return code; +} + +export const IOT_MIXIO_PUBLISHEX = function (_, generator) { + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var msg = generator.valueToCode(this, 'MSG', generator.ORDER_ATOMIC); + var q = this.getFieldValue('quality'); + generator.definitions_['import_mixiot'] = "import mixiot"; + var code = 'mqtt_client.publish(MQTT_USR_PRJ + ' + topic + ', ' + msg + ', qos='+ q +')\n'; + return code; +} + +export const IOT_MIXIO_SUBSCRIBE = function (_, generator) { + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var method = generator.valueToCode(this, 'METHOD', generator.ORDER_ATOMIC); + generator.definitions_['import_mixiot'] = "import mixiot"; + var code = 'mqtt_client.set_callback(' + topic + ',' + method + ', MQTT_USR_PRJ)\n'; + code += 'mqtt_client.subscribe(MQTT_USR_PRJ + ' + topic + ')\n'; + return code; +} + +export const iot_mixio_disconnect = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var code = 'mqtt_client.disconnect(MQTT_USR_PRJ)\n'; + return code; +} + +export const iot_mixio_connect_only = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var code = 'mqtt_client.connect()\n'; + return code; +} + +export const iot_mixio_check = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var code = 'mqtt_client.check_msg()\n'; + return code; +} + +export const iot_mixio_format_topic = function (_, generator) { + var code = 'mqtt_client.decode("utf-8").split("/")[-1]'; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_mixio_format_msg = function (_, generator) { + var code = 'mqtt_client.decode("utf-8")'; + return [code, generator.ORDER_ATOMIC]; +} + +export const IOT_FORMATTING = function (_, generator) { + generator.definitions_['import_mixpy'] = "import mixpy"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = 'mixpy.format_content(' + v + ', mqtt_client.client_id)'; + return [code, generator.ORDER_ATOMIC]; +} + +export const IOT_FORMAT_STRING = function (_, generator) { + generator.definitions_['import_mixpy'] = "import mixpy"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = 'mixpy.format_str(' + v + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const IOT_EMQX_INIT_AND_CONNECT_BY_SHARE_CODE = function (_, generator) { + var server = generator.valueToCode(this, 'SERVER', generator.ORDER_ATOMIC); + // var port = '1883'; + var share_code = generator.valueToCode(this, 'KEY', generator.ORDER_ATOMIC); + generator.definitions_['import_mixiot'] = "import mixiot"; + generator.definitions_['import_mixpy_analyse_sharekey'] = "from mixpy import analyse_sharekey"; + // var mac_address = 'str(binascii.hexlify(wifi.radio.mac_address))[2:14]' + // var socket_pool = 'socketpool.SocketPool(wifi.radio)' + // var ssl_context = 'ssl.create_default_context()' + var code = 'sk = analyse_sharekey(\'https://' + server.substring(1, server.length - 1) + '/mixio-php/sharekey.php?sk=' + share_code + '\')\n' + + 'MQTT_USR_PRJ = sk[0]+\'/\'+sk[1]+\'/\'\n'; + + // 根据server是否包含":"来生成不同的mqtt_client代码 + if (server.indexOf(':') !== -1) { + // 包含":",使用server.substring(1, server.indexOf(':')) + code += 'mqtt_client = mixiot.init_MQTT_client(' + server.substring(0, server.indexOf(':')) + server.substring(server.length - 1) + ', sk[0], sk[2]' + ', MQTT_USR_PRJ)\n'; + } else { + // 不包含":",使用完整的server(去掉首尾的引号) + code += 'mqtt_client = mixiot.init_MQTT_client(' + server.substring(0, server.length - 1)+ server.substring(server.length - 1) + ', sk[0], sk[2]' + ', MQTT_USR_PRJ)\n'; + } + return code; +} + + +export const iot_mixly_key = function (_, generator) { + var code = this.getFieldValue('VISITOR_ID'); + return [code, generator.ORDER_ATOMIC]; +} + +export const IOT_EMQX_INIT_AND_CONNECT_BY_MIXLY_CODE = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var server = generator.valueToCode(this, 'SERVER', generator.ORDER_ATOMIC); + // var port = '1883'; + var username = '"MixIO_public"'; + var password = '"MixIO_public"'; + var mixly_code = generator.valueToCode(this, 'KEY', generator.ORDER_ATOMIC); + var a = '"MixIO/' + mixly_code + '/default/"' + // var mac_address = 'str(binascii.hexlify(wifi.radio.mac_address))[2:14]' + // var socket_pool = 'socketpool.SocketPool(wifi.radio)' + // var ssl_context = 'ssl.create_default_context()' + var code = 'MQTT_USR_PRJ = ' + a + '\n' + 'mqtt_client = mixiot.init_MQTT_client(' + server + ', ' + username + ', ' + password + ', MQTT_USR_PRJ)\n'; + return code; +} + +export const IOT_EMQX_PING = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var code = 'mqtt_client.pingSync()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const IOT_MIXIO_NTP = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var code = 'mixiot.ntp(' + addr + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_client_onboard = function (_, generator) { + var code = 'mqtt_client'; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_http_client = function (_, generator) { + generator.definitions_['import_debugnet'] = "import debugnet"; + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = 'HTTP_client = debugnet.request("GET", ' + addr + ', debug=' + key + ')\n'; + return code; +} + +export const iot_http_data = function (_, generator) { + generator.definitions_['import_debugnet'] = "import debugnet"; + var key = this.getFieldValue('key'); + var code = 'HTTP_client.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_mqtt_client = function (_, generator) { + generator.definitions_['import_debugnet'] = "import debugnet"; + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key2'); + var code = 'mqtt_client = debugnet.init_MQTT_client(' + addr + ', "MixIO_public", "MixIO_public", "MixIO/3QBAGKRL/default/",debug=' + key + ')\n'; + code += 'mqtt_client.subscribe("$SYS/hello")\n'; + return code; +} + +export const iot_mqtt_data = function (_, generator) { + generator.definitions_['import_mixiot'] = "import mixiot"; + var key = this.getFieldValue('key'); + var code = 'mqtt_client.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_connect_ollama = function (_, generator) { + generator.definitions_['import_ollama'] = "from ollama import Ollama"; + var ser = generator.valueToCode(this, 'SERVER', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'NAME', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NUMBER', generator.ORDER_ATOMIC); + var code = 'llm = Ollama(' + ser + ', ' + name + ', ' + num + ')\n'; + return code; +} + +export const IOT_CONNECT_OLLAMA = iot_connect_ollama; + +export const iot_connect_openai = function (_, generator) { + generator.definitions_['import_openai'] = "from openai import OpenAI"; + var ser = generator.valueToCode(this, 'SERVER', generator.ORDER_ATOMIC); + var key = generator.valueToCode(this, 'KEY', generator.ORDER_ATOMIC); + var name = generator.valueToCode(this, 'NAME', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NUMBER', generator.ORDER_ATOMIC); + var code = `llm = OpenAI(${ser}, ${key}, ${name}, ${num})\n`; + return code; +} + +export const use_ollama_llm_to_chat = function (_, generator) { + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var method = generator.valueToCode(this, 'METHOD', generator.ORDER_ATOMIC); + var code = 'llm.chat(' + topic + ', ' + method + ')\n'; + return code; +} + +export const use_ollama_llm_to_chat_return = function (_, generator) { + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var code = 'llm.chat(' + topic + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +// export const ollama_set_timeout = function (_,generator) { +// var t = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); +// var code = 'llm.set_timeout(' + t + ')\n'; +// return code; +// } + +// export const ollama_set_max_retries = function (_,generator) { +// var t = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); +// var code = 'llm.set_max_retries(' + t + ')\n'; +// return code; +// } + +// export const ollama_set_custom_url = function (_,generator) { +// var t = generator.valueToCode(this, 'TEXT', generator.ORDER_ATOMIC); +// var code = 'llm.set_custom_url(' + t + ')\n'; +// return code; +// } + +// export const ollama_select_model = function (_,generator) { +// var t = generator.valueToCode(this, 'TEXT', generator.ORDER_ATOMIC); +// var code = 'llm.select_model(' + t + ')\n'; +// return code; +// } + +// export const ollama_clear_user_history = function (_,generator) { +// var code = 'llm.clear_user_history()\n'; +// return code; +// } + +export const ollama_empty_history = function () { + var code = 'llm.empty_history()\n'; + return code; +} + +export const iot_tiny_web_db_init = function (_,generator) { + generator.definitions_['import_tiny_webdb'] = 'import tiny_webdb'; + const addr = generator.valueToCode(this, 'ADDR', generator.ORDER_ATOMIC); + const username = generator.valueToCode(this, 'USERNAME', generator.ORDER_ATOMIC); + const password = generator.valueToCode(this, 'PASSWORD', generator.ORDER_ATOMIC); + const code = `webdb = tiny_webdb.TinyWebDB(${addr}, ${username}, ${password})\n`; + return code; +} + +export const iot_tiny_web_db_init_with_mqtt = function (_,generator) { + generator.definitions_['import_tiny_webdb'] = 'import tiny_webdb'; + const mqtt = generator.valueToCode(this, 'MQTT', generator.ORDER_ATOMIC); + const code = `webdb = tiny_webdb.TinyWebDB(${mqtt})\n`; + return code; +} + +export const iot_tiny_web_db_update = function (_,generator) { + const tag = generator.valueToCode(this, 'TAG', generator.ORDER_ATOMIC); + const value = generator.valueToCode(this, 'VALUE', generator.ORDER_ATOMIC); + const code = `webdb.update(${tag}, ${value})\n`; + return code; +} + +export const iot_tiny_web_db_get = function (_,generator) { + const tag = generator.valueToCode(this, 'TAG', generator.ORDER_ATOMIC); + const code = `webdb.get(${tag})`; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_tiny_web_db_count = function (_,generator) { + const code = 'webdb.count()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_tiny_web_db_search = function (_,generator) { + const no = generator.valueToCode(this, 'NO', generator.ORDER_ATOMIC); + const count = generator.valueToCode(this, 'COUNT', generator.ORDER_ATOMIC); + const tag = generator.valueToCode(this, 'TAG', generator.ORDER_ATOMIC); + const dtype = this.getFieldValue('DTYPE'); + const code = `webdb.search(${no}, ${count}, ${tag}, '${dtype}')`; + return [code, generator.ORDER_ATOMIC]; +} + +export const iot_tiny_web_db_delete = function (_,generator) { + const tag = generator.valueToCode(this, 'TAG', generator.ORDER_ATOMIC); + const code = `webdb.delete(${tag})\n`; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/network.js b/mixly/boards/default_src/micropython/generators/network.js new file mode 100644 index 00000000..370ae31f --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/network.js @@ -0,0 +1,319 @@ +import * as Blockly from 'blockly/core'; + +export const network_init = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('mode'); + return "" + varName + " = network.WLAN(network." + mode + "_IF);\n"; +} + +// export const network_connect = function() { +// generator.definitions_['import_network'] = "import network"; +// // generator.setups_['class_wlan'] ='wlan.active(True)\n'; +// var varName =generator.valueToCode(this, 'VAR',generator.ORDER_ATOMIC); +// var id = generator.valueToCode(this, 'id', generator.ORDER_ATOMIC); +// var password = generator.valueToCode(this, 'password', generator.ORDER_ATOMIC); +// return "if not "+varName+".isconnected():\n"+ +// " "+varName+".connect("+id+","+password+")\n"+ +// " while not "+varName+".isconnected():\n"+ +// " pass\n"; +// } + +export const network_connect = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + // generator.setups_['class_wlan'] ='wlan.active(True)\n'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var id = generator.valueToCode(this, 'id', generator.ORDER_ATOMIC); + var password = generator.valueToCode(this, 'password', generator.ORDER_ATOMIC); + return "" + varName + ".connect(" + id + ", " + password + ")\n" +} + +export const network_wifi_connect = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = varName + '.isconnected()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const network_get_connect = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('mode'); + var code = "" + varName + ".ifconfig()[" + mode + "]"; + return [code, generator.ORDER_ATOMIC] +} + +export const network_stop = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return "" + varName + ".disconnect()\n"; +} + +export const network_open = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var op = this.getFieldValue('op'); + var code = "" + varName + ".active(" + op + ")\n"; + return code; +} + +export const network_is_active = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + varName + ".active()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const network_get_wifi = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var op = this.getFieldValue('op'); + var code = "" + varName + ".config('" + op + "')"; + return [code, generator.ORDER_ATOMIC] +} + +export const network_ap_connect = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + // generator.setups_['class_wlan'] ='ap = network.WLAN(network.AP_IF)\n'+'ap.active(True)\n'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var essid = generator.valueToCode(this, 'essid', generator.ORDER_ATOMIC); + var pw = generator.valueToCode(this, 'password', generator.ORDER_ATOMIC); + var channel = generator.valueToCode(this, 'channel', generator.ORDER_ATOMIC); + return "" + varName + ".config(essid = " + essid + ", channel=" + channel + ",password="+ pw +")\n"; +} + +export const network_scan = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + varName + ".scan()"; + return [code, generator.ORDER_ATOMIC]; + +} + +export const network_server = function (_, generator) { + generator.definitions_['import_server_*'] = 'from server import *'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + // generator.setups_['class_wlan'] ='SSID="ying"\n'+'PASSWORD="201411132040"\n'; + return 'if not ' + varName + '.isconnected():\n' + + ' connectWifi(SSID, PASSWORD)\n' + + 'ip=' + varName + '.ifconfig()[0]\n' + + 'print(ip)\n' + + 'time.sleep(1)\n' + + 'DATA=listenData()\n' +} + +export const network_socket_init = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('mode'); + if (mode == 'UDP') { + mode = 'socket.SOCK_DGRAM' + } + else if (mode == 'TCP') { + mode = 'socket.SOCK_STREAM' + } + return "" + varName + " = socket.socket(socket.AF_INET, " + mode + ")\n"; +} + +export const network_socket_bind = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var address = generator.valueToCode(this, 'address', generator.ORDER_ATOMIC); + return "" + varName + ".bind(" + address + ")\n"; +} + +export const network_socket_connect = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var address = generator.valueToCode(this, 'address', generator.ORDER_ATOMIC); + return "" + varName + ".connect(socket.getaddrinfo" + address + "[0][-1])\n"; +} + +export const network_socket_listen = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var queue = generator.valueToCode(this, 'queue', generator.ORDER_ATOMIC); + return "" + varName + ".listen(" + queue + ")\n"; +} + +export const network_socket_accept = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + varName + ".accept()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const network_socket_readline = function (_, generator) { + generator.definitions_['import_network'] = 'import network'; + generator.definitions_['import_socket'] = 'import socket'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = varName + '.readline()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const network_socket_receive = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var size = generator.valueToCode(this, 'size', generator.ORDER_ATOMIC); + var code = "" + varName + ".recv(" + size + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const network_socket_send = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var content = generator.valueToCode(this, 'content', generator.ORDER_ATOMIC); + var code = "" + varName + ".send(" + content + ")\n"; + return code; +} + +export const network_socket_receive_from = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var size = generator.valueToCode(this, 'size', generator.ORDER_ATOMIC); + var code = "" + varName + ".recvfrom(" + size + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const network_socket_send_to = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var content = generator.valueToCode(this, 'content', generator.ORDER_ATOMIC); + var address = generator.valueToCode(this, 'address', generator.ORDER_ATOMIC); + var code = "" + varName + ".sendto(" + content + ", " + address + ")\n"; + return code; +} + +export const network_socket_close = function (_, generator) { + generator.definitions_['import_network'] = "import network"; + generator.definitions_['import_socket'] = "import socket"; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "" + varName + ".close()\n"; + return code; +} + +export const requests_get = function (_, generator) { + generator.definitions_.import_requests = "import requests"; + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + var str = generator.valueToCode(this, 'DOMAIN', generator.ORDER_ATOMIC); + var code = varName + '= ' + 'requests.get(' + str + ')\n'; + return code; +} + +export const requests_attribute = function (_, generator) { + generator.definitions_.import_requests = "import requests"; + var varName = generator.valueToCode(this, 'VAL', generator.ORDER_ASSIGNMENT) || '0'; + var attr = this.getFieldValue('ATTR'); + var code = varName + "." + attr; + return [code, generator.ORDER_ATOMIC]; +} + +export const requests_method = function (_, generator) { + generator.definitions_.import_requests = "import requests"; + var method = this.getFieldValue('DIR'); + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "requests." + method + "(" + str + ')\n'; + return code; +} + +export const ntptime_time = function (_, generator) { + generator.definitions_['import_ntptime'] = "import ntptime"; + var str = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var code = "ntptime.time(host=" + str + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const ntptime_address = function (_, generator) { + var code = "'" + this.getFieldValue('op') + "'"; + return [code, generator.ORDER_ATOMIC]; +} + +export const requests_get2 = function (_, generator) { + generator.definitions_['import_urequests'] = "import urequests"; + var dropdown_type = this.getFieldValue('TYPE'); + var str = generator.valueToCode(this, 'URL', generator.ORDER_ATOMIC); + var code = 'urequests.' + dropdown_type + '(' + str + ')'; + return [code, generator.ORDER_ATOMIC]; +}; + +export const requests_attribute2 = function (_, generator) { + generator.definitions_['import_urequests'] = "import urequests"; + var varName = generator.valueToCode(this, 'VAL', generator.ORDER_ASSIGNMENT) || '0'; + var attr = this.getFieldValue('ATTR'); + var code = varName + "." + attr; + return [code, generator.ORDER_ATOMIC]; +}; + +export const requests_post = function (_, generator) { + generator.definitions_['import_urequests'] = "import urequests"; + var dropdown_type = this.getFieldValue('TYPE'); + var str = generator.valueToCode(this, 'URL', generator.ORDER_ATOMIC); + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var code = 'urequests.' + dropdown_type + '(' + str + ', data=' + data + ')'; + return [code, generator.ORDER_ATOMIC]; + +}; + +export const educore_wifi_connect = function (_, generator) { + generator.definitions_['import_educore_wifi'] = "from educore import wifi"; + var username = generator.valueToCode(this, 'WIFINAME', generator.ORDER_ATOMIC); + var password = generator.valueToCode(this, 'PASSWORD', generator.ORDER_ATOMIC); + var timeout = generator.valueToCode(this, 'TIMEOUT', generator.ORDER_ATOMIC); + var code = 'wifi.connect(ssid='+username+', psd='+password+', timeout='+timeout+')\n'; + return code; +} + +export const educore_mqtt_connect = function (_, generator) { + generator.definitions_['import_educore_mqttclient'] = "from educore import mqttclient"; + var server = generator.valueToCode(this, 'SERVER', generator.ORDER_ATOMIC); + var port = generator.valueToCode(this, 'PORT', generator.ORDER_ATOMIC); + var client_id = generator.valueToCode(this, 'CLIENT_ID', generator.ORDER_ATOMIC); + var username = generator.valueToCode(this, 'USERNAME', generator.ORDER_ATOMIC); + var password = generator.valueToCode(this, 'PASSWORD', generator.ORDER_ATOMIC); + // var a = "'" + username.replace("'", "").replace("'", "") + "/" + project.replace("'", "").replace("'", "") + "/'" + // var code = 'MQTT_USR_PRJ = ' + a + '\n' + 'mqtt_client = mixiot.init_MQTT_client(' + server + ', ' + username + ', ' + password + ', MQTT_USR_PRJ)\n'; + var code = 'mqttclient.connect(server='+server+', port='+port+', client_id='+client_id+', user='+username+', psd='+password+')\n' + return code; +} + +export const educore_mqtt_subscribe_message = function (_, generator) { + generator.definitions_['import_educore_mqttclient'] = "from educore import mqttclient"; + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var message = generator.valueToCode(this, 'MESSAGE', generator.ORDER_ATOMIC); + var code = 'mqttclient.'+message+'(' + topic + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_mqtt_topic_subscribe = function (_, generator) { + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var method = generator.valueToCode(this, 'METHOD', generator.ORDER_ATOMIC); + generator.definitions_['import_educore_mqttclient'] = "from educore import mqttclient"; + // var code = 'mqtt_client.set_callback(' + topic + ',' + method + ', MQTT_USR_PRJ)\n'; + // code += 'mqtt_client.subscribe(MQTT_USR_PRJ + ' + topic + ')\n'; + var code = 'mqttclient.received(topic='+topic+', callback='+method+')\n'; + return code; +} + +export const educore_mqtt_topic_publish = function (_, generator) { + generator.definitions_['import_educore_mqttclient'] = "from educore import mqttclient"; + var topic = generator.valueToCode(this, 'TOPIC', generator.ORDER_ATOMIC); + var msg = generator.valueToCode(this, 'MSG', generator.ORDER_ATOMIC); + var code = 'mqtt_client.publish(topic=' + topic + ', content=' + msg + ')\n'; + return code; +} + +export const educore_mqtt_connect_success = function (_, generator) { + generator.definitions_['import_educore_mqttclient'] = "from educore import mqttclient"; + var code = 'mqtt_client.connescted()'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/nova_g1.js b/mixly/boards/default_src/micropython/generators/nova_g1.js new file mode 100644 index 00000000..3d78504e --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/nova_g1.js @@ -0,0 +1,29 @@ +export const get_potential_num = function (_, generator) { + generator.definitions_['from_nova_g1_import_ext_g1'] = 'from nova_g1 import ext_g1'; + var code = 'ext_g1.varistor()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const nova_g1_motor = function (_, generator) { + generator.definitions_['from_nova_g1_import_ext_g1'] = 'from nova_g1 import ext_g1'; + var wheel = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var v = this.getFieldValue('direction'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = "ext_g1.motor(" + wheel + ', "' + v + '", ' + speed + ")\n"; + return code; +} + +export const nova_g1_usb = function (_, generator) { + generator.definitions_['from_nova_g1_import_ext_g1'] = 'from nova_g1 import ext_g1'; + var p = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var percent = generator.valueToCode(this, 'percent', generator.ORDER_ATOMIC); + var code = "ext_g1.usb_pwm(" + p + ', ' + percent + ")\n"; + return code; +} + +export const nova_g1_spk_en = function (_, generator) { + generator.definitions_['from_nova_g1_import_ext_g1'] = 'from nova_g1 import ext_g1'; + var state = this.getFieldValue('state'); + var code = "ext_g1.spk_en(" + state + ")\n"; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/pe_g1.js b/mixly/boards/default_src/micropython/generators/pe_g1.js new file mode 100644 index 00000000..2869a724 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/pe_g1.js @@ -0,0 +1,67 @@ +export const pe_g1_use_i2c_init = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var code = v + ' = pe_g1.PE_G1(' + iv + ')\n'; + return code; +} + +export const pe_g1_battery_left = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + '.read_bat()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const pe_g1_dc_motor = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var s = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var wheel = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var v = this.getFieldValue('direction'); + var speed = generator.valueToCode(this, 'speed', generator.ORDER_ATOMIC); + var code = s + ".motor(" + wheel + ', "' + v + '", ' + speed + ")\n"; + return code; +} + +export const pe_g1_dc_motor_speed = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var s = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var wheel = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var v = 'NC'; + var code = s + ".motor(" + wheel + ', "' + v + '"' + ")\n"; + return [code, generator.ORDER_ATOMIC]; +} + +export const pe_g1_servo_set_angle = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var code = v + '.servo180(' + dropdown_pin + ', ' + num + ')\n'; + return code; +} + +export const pe_g1_servo_set_speed = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var code = v + '.servo360(' + dropdown_pin + ', ' + num + ')\n'; + return code; +} + +export const pe_g1_servo_get_angle = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = v + '.servo180(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const pe_g1_servo_get_speed = function (_, generator) { + generator.definitions_['import_pe_g1'] = 'import pe_g1'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = v + '.servo360(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/pins.js b/mixly/boards/default_src/micropython/generators/pins.js new file mode 100644 index 00000000..b3d02813 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/pins.js @@ -0,0 +1,30 @@ +export const pins_digital = function (_, generator) { + var code = this.getFieldValue('PIN'); + return [code, generator.ORDER_ATOMIC]; +} + +export const pins_button = pins_digital; +export const pins_digital_pin = pins_digital; +export const pins_analog_pin = pins_digital; +export const pins_analog = pins_digital; +export const pins_pwm_pin = pins_digital; +export const pins_pwm = pins_digital; +export const pins_dac_pin = pins_digital; +export const pins_dac = pins_digital; +export const pins_touch_pin = pins_digital; +export const pins_touch = pins_digital; +export const espnow_channel = pins_digital; +export const pins_interrupt = pins_digital; +export const pins_serial = pins_digital; +export const pins_builtinimg = pins_digital; +export const pins_imglist = pins_digital; +export const pins_playlist = pins_digital; +export const pins_axis = pins_digital; +export const pins_exlcdh = pins_digital; +export const pins_exlcdv = pins_digital; +export const pins_brightness = pins_digital; +export const pins_tone_notes = pins_digital; +export const pins_radio_power = pins_digital; +export const pins_radio_datarate = pins_digital; +export const pins_one_more = pins_digital; +export const pins_digital_dot = pins_digital; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/sensor.js b/mixly/boards/default_src/micropython/generators/sensor.js new file mode 100644 index 00000000..e347d8e2 --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/sensor.js @@ -0,0 +1,405 @@ +import { sensor_LTR308 } from './sensor_onboard'; + +export const sensor_mixgo_button_is_pressed = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var code = 'mixgo.' + btn + '.is_pressed()'; + return [code, generator.ORDER_ATOMIC]; +} + +//ok +export const sensor_mixgo_button_was_pressed = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var code = 'mixgo.' + btn + '.was_pressed()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_button_get_presses = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'mixgo.' + btn + '.get_presses(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_button_attachInterrupt = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo'] = 'import mixgo'; + var dropdown_btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var dropdown_mode = this.getFieldValue('mode'); + var atta = generator.valueToCode(this, 'DO', generator.ORDER_ATOMIC); + var code = 'mixgo.' + dropdown_btn + '.irq' + '(handler=' + atta + ', trigger=' + dropdown_mode + ')\n' + return code; +} + +//ok +export const sensor_mixgo_extern_button_is_pressed = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = 'mixgo.Button(' + pin + ').is_pressed(' + dropdown_stat + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +//ok +export const sensor_mixgo_extern_button_was_pressed = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = 'mixgo.Button(' + pin + ').was_pressed(' + dropdown_stat + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_button_get_presses = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'mixgo.Button(' + pin + ').get_presses(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_button_attachInterrupt = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_mode = this.getFieldValue('mode'); + var atta = generator.valueToCode(this, 'DO', generator.ORDER_ATOMIC); + var code = 'mixgo.Button(' + pin + ').irq' + '(handler=' + atta + ', trigger=' + dropdown_mode + ')\n' + return code; +} + +//ok +export const sensor_mpu9250_attachGestureInterrupt = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var gesture = this.getFieldValue('gesture'); + var branch = generator.statementToCode(this, 'DO'); + var d = branch || generator.PASS; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = 'if ' + v + '.mpu9250_is_gesture("' + gesture + '"):\n' + d; + return code; +} + +export const sensor_mpu9250_gesture = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var gesture = this.getFieldValue('gesture'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_is_gesture("' + gesture + '")'; + return [code, generator.ORDER_ATOMIC]; +} + +//ok +export const sensor_mpu9250_get_acceleration = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_get_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_adxl345_get_acceleration = function (_, generator) { + generator.definitions_['import_adxl345'] = 'import adxl345'; + // generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code; + if (key == 'x') { + code = v + '.readX()'; + } else if (key == 'y') { + code = v + '.readY()'; + } else if (key == 'z') { + code = v + '.readZ()'; + } else if (key == 'values') { + code = v + '.readXYZ()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_get_magnetic = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_magnetic_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_get_gyro = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_gyro_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_calibrate_compass = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_compass'] = 'from mixgo import compass'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + return '' + v + '.calibrate()\n'; +} + +export const sensor_mpu9250_temperature = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + return [v + '.mpu9250_get_temperature()', generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_field_strength = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "compass") + generator.definitions_['import_mixgo_compass'] = 'from mixgo import compass'; + var compass = this.getFieldValue('compass'); + var a; + if (compass == 'strength') { + a = v + '.get_field_strength()'; + } + else if (compass == 'heading') { + a = v + '.heading()'; + } + return [a, generator.ORDER_ATOMIC]; +} + +export const sensor_distance_hrsc04 = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + generator.setups_['class_hrsc04'] = + 'class HCSR04:\n' + + ' def __init__(self, tpin=pin15, epin=pin14, spin=pin13):\n' + + ' self.trigger_pin = tpin\n' + + ' self.echo_pin = epin\n' + + ' self.sclk_pin = spin\n' + + '\n' + + ' def distance_mm(self):\n' + + ' spi.init(baudrate=125000, sclk=self.sclk_pin,\n' + + ' mosi=self.trigger_pin, miso=self.echo_pin)\n' + + ' pre = 0\n' + + ' post = 0\n' + + ' k = -1\n' + + ' length = 500\n' + + ' resp = bytearray(length)\n' + + ' resp[0] = 0xFF\n' + + ' spi.write_readinto(resp, resp)\n' + + ' # find first non zero value\n' + + ' try:\n' + + ' i, value = next((ind, v) for ind, v in enumerate(resp) if v)\n' + + ' except StopIteration:\n' + + ' i = -1\n' + + ' if i > 0:\n' + + ' pre = bin(value).count("1")\n' + + ' # find first non full high value afterwards\n' + + ' try:\n' + + ' k, value = next((ind, v)\n' + + ' for ind, v in enumerate(resp[i:length - 2]) if resp[i + ind + 1] == 0)\n' + + ' post = bin(value).count("1") if k else 0\n' + + ' k = k + i\n' + + ' except StopIteration:\n' + + ' i = -1\n' + + ' dist= -1 if i < 0 else round((pre + (k - i) * 8. + post) * 8 * 0.172)\n' + + ' return dist\n' + + '\n' + + 'sonar=HCSR04()\n' + return ['sonar.distance_mm() / 10.0', generator.ORDER_ATOMIC]; +} + +export const RTC_get_time = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "rtc") + generator.definitions_['import_mixgo_rtc'] = 'from mixgo import rtc'; + var code = v + '.datetime()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const RTC_set_time = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var hour = generator.valueToCode(this, "hour", generator.ORDER_ASSIGNMENT); + var minute = generator.valueToCode(this, "minute", generator.ORDER_ASSIGNMENT); + var second = generator.valueToCode(this, "second", generator.ORDER_ASSIGNMENT); + generator.setups_['class_DS1307'] = generator.CLASS_DS1307_INIT; + var code = 'str(ds.Hour(' + hour + ')) + str(ds.Minute(' + minute + ')) + str(ds.Second(' + second + '))\n'; + return code; +} + +export const RTC_set_date = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var year = generator.valueToCode(this, "year", generator.ORDER_ASSIGNMENT); + var month = generator.valueToCode(this, "month", generator.ORDER_ASSIGNMENT); + var day = generator.valueToCode(this, "day", generator.ORDER_ASSIGNMENT); + generator.setups_['class_DS1307'] = generator.CLASS_DS1307_INIT; + var code = 'str(ds.Year(' + year + ')) + str(ds.Month(' + month + ')) + str(ds.Day(' + day + '))\n'; + return code; +} + +export const sensor_compass_reset = function (block, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_compass'] = 'from mixgo import compass'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + return '' + v + '.reset_calibrate()\n'; +} + +export const HCSR04 = function (_, generator) { + generator.definitions_['import_sonar'] = 'import sonar'; + var dropdown_pin1 = generator.valueToCode(this, "PIN1", generator.ORDER_ASSIGNMENT); + var dropdown_pin2 = generator.valueToCode(this, "PIN2", generator.ORDER_ASSIGNMENT); + var code = 'sonar.Sonar(' + dropdown_pin1 + ', ' + dropdown_pin2 + ').checkdist()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_dht11 = function (_, generator) { + generator.definitions_['import_dhtx'] = 'import dhtx'; + var sensor_type = this.getFieldValue('TYPE'); + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var what = this.getFieldValue('WHAT'); + var code = 'dhtx.get_dht_' + what + "('" + sensor_type + "', " + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_light = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'mixgo.get_brightness(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_sound = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'mixgo.get_soundlevel(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const number1 = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_pin_pressed = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'button', generator.ORDER_ATOMIC); + var code = 'mixgo.' + pin + '.is_touched()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_pin_near = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'mixgo.' + 'Infrared(' + pin + ')()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_pin_near = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var direction = this.getFieldValue('direction'); + var code = 'mixgo.' + 'infrared_' + direction + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const RTC_set_datetime = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var year = generator.valueToCode(this, "year", generator.ORDER_ASSIGNMENT); + var month = generator.valueToCode(this, "month", generator.ORDER_ASSIGNMENT); + var day = generator.valueToCode(this, "day", generator.ORDER_ASSIGNMENT); + var hour = generator.valueToCode(this, "hour", generator.ORDER_ASSIGNMENT); + var minute = generator.valueToCode(this, "minute", generator.ORDER_ASSIGNMENT); + var second = generator.valueToCode(this, "second", generator.ORDER_ASSIGNMENT); + var week = generator.valueToCode(this, "weekday", generator.ORDER_ASSIGNMENT); + var millisecond = generator.valueToCode(this, "millisecond", generator.ORDER_ASSIGNMENT); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "rtc") + generator.definitions_['import_mixgo_rtc'] = 'from mixgo import rtc'; + var code = v + '.datetime((' + year + ', ' + month + ', ' + day + ', ' + week + ', ' + hour + ', ' + minute + ', ' + second + ', ' + millisecond + '))\n'; + return code; +} + +export const sensor_rtc_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + var code = v + ' = machine.RTC()\n'; + return code; +} + +export const sensor_use_i2c_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_machine'] = 'import machine'; + var code; + if (key == 'MPU9250') { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + code = v + ' = mpu9250.' + key + "(" + iv + ')\n'; + } else if (key == 'BMP280') { + generator.definitions_['import_bmp280'] = 'import bmp280'; + code = v + ' = bmp280.' + key + "(" + iv + ')\n'; + } else if (key == 'SHT20') { + generator.definitions_['import_sht20'] = 'import sht20'; + code = v + ' = sht20.' + key + "(" + iv + ')\n'; + } else if (key == 'ADXL345') { + generator.definitions_['import_adxl345'] = 'import adxl345'; + code = v + ' = adxl345.' + key + "(" + iv + ')\n'; + } + return code; +} + +export const sensor_bmp = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_bmp280'] = 'import bmp280'; + var code = v + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_sht = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_sht20'] = 'import sht20'; + var code = v + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_ds18x20 = function (_, generator) { + generator.definitions_['import_ds18x20x'] = 'import ds18x20x'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'ds18x20x.get_ds18x20_temperature(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_lm35 = function (_, generator) { + generator.definitions_['import_lm35'] = 'import lm35'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'lm35.get_LM35_temperature(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_button_is_pressed = sensor_mixgo_button_is_pressed; +export const sensor_button_was_pressed = sensor_mixgo_button_was_pressed; +export const sensor_button_get_presses = sensor_mixgo_button_get_presses; +export const sensor_pin_pressed = sensor_mixgo_pin_pressed; +export const sensor_pin_near = sensor_mixgo_pin_near; +export const sensor_mixgo_light = sensor_LTR308; +export const sensor_light = sensor_mixgo_light; +// export const sensor_get_acceleration = sensor_mixgo_get_acceleration; +export const dht11 = sensor_dht11; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/sensor_extern.js b/mixly/boards/default_src/micropython/generators/sensor_extern.js new file mode 100644 index 00000000..f4bb695b --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/sensor_extern.js @@ -0,0 +1,1189 @@ +import { Boards } from 'mixly'; + +export const sensor_mixgo_extern_button_is_pressed = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = 'mixgo.Button(' + pin + ').is_pressed(' + dropdown_stat + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +//ok +export const sensor_mixgo_extern_button_was_pressed = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_stat = generator.valueToCode(this, 'STAT', generator.ORDER_ATOMIC); + var code = 'mixgo.Button(' + pin + ').was_pressed(' + dropdown_stat + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_button_get_presses = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'mixgo.Button(' + pin + ').get_presses(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_button_attachInterrupt = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var dropdown_mode = this.getFieldValue('mode'); + var atta = generator.valueToCode(this, 'DO', generator.ORDER_ATOMIC); + var code = 'mixgo.Button(' + pin + ').irq' + '(handler=' + atta + ', trigger=' + dropdown_mode + ')\n' + return code; +} + +export const sensor_mpu9250_attachGestureInterrupt = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var gesture = this.getFieldValue('gesture'); + var branch = generator.statementToCode(this, 'DO'); + var d = branch || generator.PASS; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = 'if ' + v + '.mpu9250_is_gesture("' + gesture + '"):\n' + d; + return code; +} + +export const sensor_distance_hrsc04 = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + generator.setups_['class_hrsc04'] = + 'class HCSR04:\n' + + ' def __init__(self, tpin=pin15, epin=pin14, spin=pin13):\n' + + ' self.trigger_pin = tpin\n' + + ' self.echo_pin = epin\n' + + ' self.sclk_pin = spin\n' + + '\n' + + ' def distance_mm(self):\n' + + ' spi.init(baudrate=125000, sclk=self.sclk_pin,\n' + + ' mosi=self.trigger_pin, miso=self.echo_pin)\n' + + ' pre = 0\n' + + ' post = 0\n' + + ' k = -1\n' + + ' length = 500\n' + + ' resp = bytearray(length)\n' + + ' resp[0] = 0xFF\n' + + ' spi.write_readinto(resp, resp)\n' + + ' # find first non zero value\n' + + ' try:\n' + + ' i, value = next((ind, v) for ind, v in enumerate(resp) if v)\n' + + ' except StopIteration:\n' + + ' i = -1\n' + + ' if i > 0:\n' + + ' pre = bin(value).count("1")\n' + + ' # find first non full high value afterwards\n' + + ' try:\n' + + ' k, value = next((ind, v)\n' + + ' for ind, v in enumerate(resp[i:length - 2]) if resp[i + ind + 1] == 0)\n' + + ' post = bin(value).count("1") if k else 0\n' + + ' k = k + i\n' + + ' except StopIteration:\n' + + ' i = -1\n' + + ' dist= -1 if i < 0 else round((pre + (k - i) * 8. + post) * 8 * 0.172)\n' + + ' return dist\n' + + '\n' + + 'sonar=HCSR04()\n' + return ['sonar.distance_mm() / 10.0', generator.ORDER_ATOMIC]; +} + +export const RTC_set_time = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var hour = generator.valueToCode(this, "hour", generator.ORDER_ASSIGNMENT); + var minute = generator.valueToCode(this, "minute", generator.ORDER_ASSIGNMENT); + var second = generator.valueToCode(this, "second", generator.ORDER_ASSIGNMENT); + generator.setups_['class_DS1307'] = generator.CLASS_DS1307_INIT; + var code = 'str(ds.Hour(' + hour + '))+ str(ds.Minute(' + minute + ')) +str(ds.Second(' + second + '))\n'; + return code; +} + +export const RTC_set_date = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var year = generator.valueToCode(this, "year", generator.ORDER_ASSIGNMENT); + var month = generator.valueToCode(this, "month", generator.ORDER_ASSIGNMENT); + var day = generator.valueToCode(this, "day", generator.ORDER_ASSIGNMENT); + generator.setups_['class_DS1307'] = generator.CLASS_DS1307_INIT; + var code = 'str(ds.Year(' + year + ')) + str(ds.Month(' + month + ')) + str(ds.Day(' + day + '))\n'; + return code; +} + +export const sensor_mixgo_extern_light = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'mixgo.get_brightness(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_sound = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'mixgo.get_soundlevel(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_extern_pin_near = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var direction = this.getFieldValue('direction'); + var code = 'mixgo.' + 'infrared_' + direction + '.near()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_rtc_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_machine'] = 'import machine'; + var code = v + ' = machine.RTC()\n'; + return code; +} + +export const sensor_bmp = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_bmp280'] = 'import bmp280'; + var code = v + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_sht = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_sht20'] = 'import sht20'; + var code = v + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +//pe +export const sensor_use_i2c_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var iv = generator.valueToCode(this, 'I2CSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code; + if (key == 'MPU9250') { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + code = v + ' = mpu9250.' + key + "(" + iv + ')\n'; + } else if (key == 'BMP280') { + generator.definitions_['import_bmp280'] = 'import bmp280'; + code = v + ' = bmp280.' + key + "(" + iv + ')\n'; + } else if (key == 'SHT20') { + generator.definitions_['import_sht20'] = 'import sht20'; + code = v + ' = sht20.' + key + "(" + iv + ')\n'; + } else if (key == 'ADXL345') { + generator.definitions_['import_adxl345'] = 'import adxl345'; + code = v + ' = adxl345.' + key + "(" + iv + ')\n'; + } else if (key == 'LTR308') { + generator.definitions_['import_ltr308al'] = 'import ltr308al'; + code = v + ' = ltr308al.LTR_308ALS(' + iv + ')\n'; + } else if (key == 'LTR381RGB') { + generator.definitions_['import_ltr381rgb'] = 'import ltr381rgb'; + code = v + ' = ltr381rgb.LTR_381RGB(' + iv + ')\n'; + } else if (key == 'UCS12071') { + generator.definitions_['import_ucs12071'] = 'import ucs12071'; + code = v + ' = ucs12071.UCS12071(' + iv + ')\n'; + } else if (key == 'LTR390UV') { + generator.definitions_['import_ltr390uv'] = 'import ltr390uv'; + code = v + ' = ltr390uv.ALS_UVS(' + iv + ')\n'; + } else if (key == 'HP203X') { + generator.definitions_['import_hp203x'] = 'import hp203x'; + code = v + ' = hp203x.HP203X(' + iv + ')\n'; + } else if (key == "SPL06_001") { + generator.definitions_['import_spl06_001'] = 'import spl06_001'; + code = v + ' = spl06_001.SPL06(' + iv + ')\n'; + } else if (key == 'SHTC3') { + generator.definitions_['import_shtc3'] = 'import shtc3'; + code = v + ' = shtc3.' + key + "(" + iv + ')\n'; + } else if (key == 'AHT21') { + generator.definitions_['import_ahtx0'] = 'import ahtx0'; + code = v + ' = ahtx0.AHTx0(' + iv + ')\n'; + } else if (key == 'VL53L0X') { + generator.definitions_['import_vl53l0x'] = 'import vl53l0x'; + code = v + ' = vl53l0x.' + key + "(" + iv + ')\n'; + } else if (key == 'QMC5883L') { + generator.definitions_['import_qmc5883l'] = 'import qmc5883l'; + code = v + ' = qmc5883l.Compass(' + iv + ')\n'; + } else if (key == 'MAX30102') { + generator.definitions_['import_max30102'] = 'import max30102'; + code = v + ' = max30102.MAX30102(' + iv + ')\n'; + } else if (key == 'APDS9960') { + generator.definitions_['import_apds9960'] = 'import apds9960'; + code = v + ' = apds9960.APDS9960(' + iv + ')\n'; + } else if (key == 'RFID') { + generator.definitions_['import_rc522'] = 'import rc522'; + code = v + ' = rc522.RC522(' + iv + ')\n'; + } else if (key == 'CBR817') { + generator.definitions_['import_cbr817'] = 'import cbr817'; + code = v + ' = cbr817.' + key + "(" + iv + ')\n'; + } else if (key == 'CI130X') { + generator.definitions_['import_ci130x'] = 'import ci130x'; + code = v + ' = ci130x.' + key + "(" + iv + ')\n'; + } else if (key == 'MS5611') { + generator.definitions_['import_ms5611'] = 'import ms5611'; + code = v + ' = ms5611.MS5611(' + iv + ')\n'; + }else if (key == 'AGS10'){ + generator.definitions_['import_ags10'] = 'import ags10'; + code = v + ' = ags10.AGS10(' + iv + ')\n'; + } + return code; +} + +export const radar_set_DETECTION_THRESHOLD = function (_, generator) { + generator.definitions_['import_cbr817'] = 'import cbr817'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var value = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var value2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var code = sub + '.threshold(' + value + ')\n' + sub + '.delay_ms(' + value2 + ')\n'; + return code; +} + +export const radar_set_DETECTION_THRESHOLD_SANT = function (_, generator) { + generator.definitions_['import_sant_gx_ext_mmw'] = 'from sant_gx import ext_mmw'; + var value = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var value2 = generator.valueToCode(this, 'VAR2', generator.ORDER_ATOMIC); + var code = 'ext_mmw.threshold(' + value + ')\n' + 'ext_mmw.delay_ms(' + value2 + ')\n'; + return code; +} + +export const interaction_whether_to_interaction = function (_, generator) { + generator.definitions_['import_cbr817'] = 'import cbr817'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.result()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const interaction_whether_to_interaction_SANT = function (_, generator) { + generator.definitions_['import_sant_gx_ext_mmw'] = 'from sant_gx import ext_mmw'; + var code = 'ext_mmw.result()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const CI130X_IDENTIFY_AND_SAVE = function (_, generator) { + generator.definitions_['import_ci130x'] = 'import ci130x'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.cmd_id()\n'; + return code; +} + +export const CI130X_GET_WHETHER_IDENTIFY = function (_, generator) { + generator.definitions_['import_ci130x'] = 'import ci130x'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var cmd = this.getFieldValue('cmd'); + var code = sub + '.result(' + cmd + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const CI130X_GET_THE_RECOGNIZED_CMD = function (_, generator) { + generator.definitions_['import_ci130x'] = 'import ci130x'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + if (key == 'status1') { + var code = sub + '.status()[0]'; + } else if (key == 'status2') { + var code = sub + '.status()[1]'; + } else { + var code = sub + '.' + key + '()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const CI130X_BROADCAST = function (_, generator) { + generator.definitions_['import_ci130x'] = 'import ci130x'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var num = generator.valueToCode(this, 'NUM', generator.ORDER_ATOMIC); + var star = this.getFieldValue('star'); + var end = this.getFieldValue('end'); + var code = sub + '.play(' + star + ', ' + num + ', ' + end + ')\n'; + return code; +} + +export const CI130X_SET_SYSTEM_CMD = function (_, generator) { + generator.definitions_['import_ci130x'] = 'import ci130x'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var cmd = this.getFieldValue('cmd'); + var code = sub + '.sys_cmd(' + cmd + ')\n'; + return code; +} + +export const sensor_MAX30102_extern = function (_, generator) { + generator.definitions_['import_max30102'] = 'import max30102'; + var key = this.getFieldValue('key'); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.heartrate()' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_APDS9960_extern = function (_, generator) { + generator.definitions_['import_apds9960'] = 'import apds9960'; + var key = this.getFieldValue('key'); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_LTR308_extern = function (_, generator) { + generator.definitions_['import_ltr308al'] = 'import ltr308al'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.getdata()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_hp203_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_hp203x'] = 'import hp203x'; + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_spl06_001_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_spl06_001'] = 'import spl06_001'; + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_ms5611_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_ms5611'] = 'import ms5611'; + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_ms5611_extern_altitude = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + generator.definitions_['import_ms5611'] = 'import ms5611'; + var code = sub + '.altitude('+ v +')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_ltr381_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_ltr381rgb'] = 'import ltr381rgb'; + var code = sub + '.getdata()' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_ucs12071_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_ucs12071'] = 'import ucs12071'; + if (key == '0') { + var code = sub + '.color()'; + } else if (key == '1') { + var code = sub + '.color_raw()'; + } else if (key == '2') { + var code = sub + '.als()'; + } else { + var code = sub + '.ir()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_LTR390UV_extern = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_time'] = 'import time'; + generator.definitions_['import_ltr390uv'] = 'import ltr390uv'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + if (key == 'E') { + var code = sub + '.ambient_light()'; + } else { + var code = sub + '.ultraviolet()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_QMC5883L_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_qmc5883l'] = 'import qmc5883l'; + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_shtc3_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_shtc3'] = 'import shtc3'; + var code = sub + '.' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_aht11_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_ahtx0'] = 'import ahtx0'; + var code = sub + '.' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_VL530LX_extern = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_vl53l0x'] = 'import vl53l0x'; + var code = sub + '.read()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_use_spi_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sv = generator.valueToCode(this, 'SPISUB', generator.ORDER_ATOMIC); + var pv = generator.valueToCode(this, 'PINSUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code; + if (key == 'RFID') { + generator.definitions_['import_rc522'] = 'import rc522'; + var code = v + ' = rc522.RC522(' + sv + ',' + pv + ')\n'; + } else if (key == 'Weather') { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + generator.definitions_['import_ws_lora'] = 'import ws_lora'; + if (version == 'mixgo_pe') { + var code = v + ' = ws_lora.Weather(' + sv + ', ' + pv + ')\n'; + } else if (version == 'mixgo_nova') { + var code = v + ' = ws_lora.Weather(' + sv + ', ' + pv + ', ' + version + '.onboard_i2c_soft' + ')\n'; + } else { + var code = v + ' = ws_lora.Weather(' + sv + ', ' + pv + ', ' + version + '.onboard_i2c' + ')\n'; + } + } + return code; +} + +export const extern_rfid_read = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sector = generator.valueToCode(this, 'SECTOR', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_rc522'] = 'import rc522'; + var code = sub + '.read_card(' + sector + ', "' + key + '")'; + return [code, generator.ORDER_ATOMIC]; +} + +export const extern_rfid_readid = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_rc522'] = 'import rc522'; + var code = sub + '.read_card(0, x="id")'; + return [code, generator.ORDER_ATOMIC]; +} + +export const extern_rfid_readcontent = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sector = generator.valueToCode(this, 'SECTOR', generator.ORDER_ATOMIC); + generator.definitions_['import_rc522'] = 'import rc522'; + var code = sub + '.read_card(' + sector + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const extern_rfid_write = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sector = generator.valueToCode(this, 'SECTOR', generator.ORDER_ATOMIC); + var cnt = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC); + generator.definitions_['import_rc522'] = 'import rc522'; + var code = sub + '.write_card(' + cnt + ', ' + sector + ')\n'; + return code; +} + +export const extern_rfid_write_return = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sector = generator.valueToCode(this, 'SECTOR', generator.ORDER_ATOMIC); + var cnt = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC); + generator.definitions_['import_rc522'] = 'import rc522'; + var code = sub + '.write_card(' + cnt + ', ' + sector + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const extern_rfid_status = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_rc522'] = 'import rc522'; + var code = sub + '.scan_card() == ' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const weather_data = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_ws_lora'] = 'import ws_lora'; + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const weather_have_data = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_ws_lora'] = 'import ws_lora'; + var code = sub + '.any()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const weather_uart_mixio = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var base = generator.valueToCode(this, 'BASE', generator.ORDER_ATOMIC); + generator.definitions_['import_ws_lora'] = 'import ws_lora'; + var code = sub + '.uart_mixio(topic=' + base + ')\n'; + return code; +} + +export const weather_set_label = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_ws_lora'] = 'import ws_lora'; + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, generator.ORDER_NONE) || default_value; + } + var code = sub + '.label(' + code.join(', ') + ')\n'; + return code; +} + +export const sensor_mixgoce_hot_wheel_is_touched = function (_, generator) { + var key = this.getFieldValue('key'); + var stat = this.getFieldValue('stat'); + generator.definitions_['import_tpwheel'] = 'import tpwheel'; + var code = 'tpwheel.TouchPadWheels(' + key + ').' + stat; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgoce_hot_wheel_degrees = function (_, generator) { + generator.definitions_['import_tpwheel'] = 'import tpwheel'; + var code = 'tpwheel.hot_wheels_degree()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const esp32_s2_weather_init = function (_, generator) { + generator.definitions_['import_weather'] = 'import weather'; + generator.definitions_['import_board_*'] = 'from board import *'; + var wd = generator.valueToCode(this, 'wd', generator.ORDER_ATOMIC); + var ws = generator.valueToCode(this, 'ws', generator.ORDER_ATOMIC); + var rain = generator.valueToCode(this, 'rain', generator.ORDER_ATOMIC); + var code = "wd = weather.Weather_wd(" + wd + ")\n" + code += "ws = weather.Weather_ws(" + ws + ")\n" + code += "rain = weather.Weather_rain(" + rain + ")\n" + return code; +} + +export const esp32_s2_weather_wd = function (_, generator) { + generator.definitions_['import_weather'] = 'import weather'; + var code = 'wd.wind_direction()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const esp32_s2_weather_rain = function (_, generator) { + generator.definitions_['import_weather'] = 'import weather'; + var rain = generator.valueToCode(this, 'rain', generator.ORDER_ATOMIC); + var code = 'rain.rain_count(time_Hour=' + rain + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const esp32_s2_weather_ws = function (_, generator) { + generator.definitions_['import_weather'] = 'import weather'; + var key = this.getFieldValue('key'); + if (key == 'ALL') { + var code = 'ws.wind_speed()'; + } else { + var code = 'ws.wind_speed()[' + key + ']'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const HCSR04 = function (_, generator) { + generator.definitions_['import_sonar'] = 'import sonar'; + var dropdown_pin1 = generator.valueToCode(this, "PIN1", generator.ORDER_ASSIGNMENT); + var dropdown_pin2 = generator.valueToCode(this, "PIN2", generator.ORDER_ASSIGNMENT); + var code = 'sonar.Sonar(' + dropdown_pin1 + ', ' + dropdown_pin2 + ').checkdist()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const PS2_init = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + //generator.definitions_['import_board'] = 'import board'; + var PS2_CLK = this.getFieldValue('PS2_CLK'); + var PS2_DOU = this.getFieldValue('PS2_DOU'); + var PS2_DIN = this.getFieldValue('PS2_DIN'); + var PS2_CS = this.getFieldValue('PS2_CS'); + var code = 'mixgope_ps = ps2.PS2Controller(' + PS2_CLK + ', ' + PS2_DOU + ', ' + PS2_DIN + ', ' + PS2_CS + ')\n'; + return code; +} + +export const PS2_vibration = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var ss = this.getFieldValue('smotorstate'); + var amp = generator.valueToCode(this, 'AMP', generator.ORDER_ATOMIC); + var code = "mixgope_ps.PS2_vibration(" + ss + ', ' + amp + ")\n"; + return code; +} + +export const PS2_Button = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var bt = this.getFieldValue('psbt'); + var code = "mixgope_ps.PS2_keydata()[0] & (ps2." + bt + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const PS2_Buttons = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var bt = this.getFieldValue('psbt'); + var code = "ps2." + bt; + return [code, generator.ORDER_ATOMIC]; +} + +export const PS2_State = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var bt = this.getFieldValue('btstate'); + var code = "mixgope_ps.PS2_keydata()[" + bt + "]"; + return [code, generator.ORDER_ATOMIC]; +} + +export const PS2_stk = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var stk = this.getFieldValue('psstk'); + var code = "mixgope_ps.PS2_keydata()[1][" + stk + "]"; + return [code, generator.ORDER_ATOMIC]; +} + +export const RTC_set_datetime = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var year = generator.valueToCode(this, "year", generator.ORDER_ASSIGNMENT); + var month = generator.valueToCode(this, "month", generator.ORDER_ASSIGNMENT); + var day = generator.valueToCode(this, "day", generator.ORDER_ASSIGNMENT); + var hour = generator.valueToCode(this, "hour", generator.ORDER_ASSIGNMENT); + var minute = generator.valueToCode(this, "minute", generator.ORDER_ASSIGNMENT); + var second = generator.valueToCode(this, "second", generator.ORDER_ASSIGNMENT); + var week = generator.valueToCode(this, "weekday", generator.ORDER_ASSIGNMENT); + var millisecond = generator.valueToCode(this, "millisecond", generator.ORDER_ASSIGNMENT); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "rtc") + generator.definitions_['import_mixgo_rtc'] = 'from mixgo import rtc'; + var code = v + '.datetime((' + year + ', ' + month + ', ' + day + ', ' + week + ', ' + hour + ', ' + minute + ', ' + second + ', ' + millisecond + '))\n'; + return code; +} + +export const RTC_get_time = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "rtc") + generator.definitions_['import_mixgo_rtc'] = 'from mixgo import rtc'; + var code = v + '.datetime()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_dht11 = function (_, generator) { + generator.definitions_['import_dhtx'] = 'import dhtx'; + var sensor_type = this.getFieldValue('TYPE'); + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var what = this.getFieldValue('WHAT'); + var code = 'dhtx.' + sensor_type + "(" + dropdown_pin + ').' + what + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const PS2_init_new = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + //generator.definitions_['import_board'] = 'import board'; + var PS2_CLK = generator.valueToCode(this, 'CLK', generator.ORDER_ATOMIC); + var PS2_DOU = generator.valueToCode(this, 'DOU', generator.ORDER_ATOMIC); + var PS2_DIN = generator.valueToCode(this, 'DIN', generator.ORDER_ATOMIC); + var PS2_CS = generator.valueToCode(this, 'CS', generator.ORDER_ATOMIC); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + ' = ps2.PS2Controller(' + PS2_CLK + ', ' + PS2_DOU + ', ' + PS2_DIN + ', ' + PS2_CS + ')\n'; + return code; +} + +export const PS2_vibration_new = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var ss = this.getFieldValue('smotorstate'); + var amp = generator.valueToCode(this, 'AMP', generator.ORDER_ATOMIC); + var code = sub + ".vibration(" + ss + ', ' + amp + ")\n"; + return code; +} + +export const PS2_Buttons_new = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var bt = this.getFieldValue('psbt'); + var code = sub + '.button(ps2.' + bt + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const PS2_stk_new = function (_, generator) { + generator.definitions_['import_ps2'] = 'import ps2'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var stk = this.getFieldValue('psstk'); + var code = sub + ".analog(ps2.PSS_" + stk + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_use_uart_init = function (_, generator) { + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var s = this.getFieldValue('sensor'); + var code = '' + if (s == 'PM') { + generator.definitions_['import_pm2_5'] = 'import pm2_5'; + code = v + '= pm2_5.PM2_5(' + key + ')\n'; + } else if (s == 'GNSS') { + generator.definitions_['import_gnss'] = 'import gnss'; + code = v + '= gnss.NMEA0183(' + key + ')\n'; + } else if (s == 'TVOC'){ + generator.definitions_['import_tvoc07s'] = 'import tvoc07s'; + code = v + '= tvoc07s.TVOC(' + key + ')\n'; + } + return code; +} + +export const pm25_get_data = function (_, generator) { + generator.definitions_['import_pm2_5'] = 'import pm2_5'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var pm = this.getFieldValue('pm'); + var code = v + ".concentration()" + pm; + return [code, generator.ORDER_ATOMIC]; +} + +export const gnss_get_data = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + generator.definitions_['import_gnss'] = 'import gnss'; + var code = sub + '.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const gnss_have_data = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_gnss'] = 'import gnss'; + var code = sub + '.any()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tvoc_get_data = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + generator.definitions_['import_tvoc07s'] = 'import tvoc07s'; + var key = this.getFieldValue('key'); + var code = sub + '.read()'+key; + return [code, generator.ORDER_ATOMIC]; +} + +//mixbot/feiyi extern below: +export const robot_button_extern_get_value = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var num = this.getFieldValue('num'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_button'] = 'from mixbot_ext import ext_button'; + var code = 'ext_button.value(' + mode + ")" + num; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_button'] = 'ext_button_left = i2cdevice.Buttonx5(ext_i2c_left)'; + var code = 'ext_button_left.value()' + num; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_button'] = 'ext_button_right = i2cdevice.Buttonx5(ext_i2c_right)'; + var code = 'ext_button_right.value()' + num; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_touch_extern_get_value = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_collision'] = 'from mixbot_ext import ext_collision'; + var code = 'ext_collision.value(' + mode + ")"; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_collision'] = 'ext_collision_left = i2cdevice.Button(ext_i2c_left)'; + var code = 'ext_collision_left.value()'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_collision'] = 'ext_collision_right = i2cdevice.Button(ext_i2c_right)'; + var code = 'ext_collision_right.value()'; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_infrared_extern_get_value = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + if (version == 'mixbot') { + var mode = this.getFieldValue('mode'); + generator.definitions_['import_mixbot_ext_ext_infrared'] = 'from mixbot_ext import ext_infrared'; + var code = 'ext_infrared.value(' + mode + ")"; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + var mode = this.getFieldValue('mode'); + generator.definitions_['import_feiyi_onboard_bot51'] = 'from feiyi import onboard_bot51'; + var code = 'onboard_bot51.read_ps(' + mode + ")"; + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_infrared_extern_grey_get_value = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_grey_near'] = 'ext_grey_near_left = i2cdevice.Infrared(ext_i2c_left)'; + var code = 'ext_grey_near_left.value()'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right=i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_grey_near'] = 'ext_grey_near_right = i2cdevice.Infrared(ext_i2c_right)'; + var code = 'ext_grey_near_right.value()'; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_potentiometer_extern_get_value = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_potentiometer'] = 'from mixbot_ext import ext_potentiometer'; + var code = 'ext_potentiometer.value(' + mode + ")"; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_potentiometer'] = 'ext_potentiometer_left = i2cdevice.Dimmer(ext_i2c_left)'; + var code = 'ext_potentiometer_left.value()'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_potentiometer'] = 'ext_potentiometer_right = i2cdevice.Dimmer(ext_i2c_right)'; + var code = 'ext_potentiometer_right.value()'; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_color_extern_get_value = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var color = this.getFieldValue('color'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_color'] = 'from mixbot_ext import ext_color'; + var code = 'ext_color.recognition(' + mode + ")" + color; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_color'] = 'ext_color_left = i2cdevice.Color_ID(ext_i2c_left)'; + var code = 'ext_color_left.recognition()' + color; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_color'] = 'ext_color_right = i2cdevice.Color_ID(ext_i2c_right)'; + var code = 'ext_color_right.recognition()' + color; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_sonar_extern_get_value = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_sonar'] = 'from mixbot_ext import ext_sonar'; + var code = 'ext_sonar.value(' + mode + ")"; + return [code, generator.ORDER_ATOMIC]; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_sonar'] = 'ext_sonar_left = i2cdevice.Sonar(ext_i2c_left)'; + var code = 'ext_sonar_left.value()'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_sonar'] = 'ext_sonar_right = i2cdevice.Sonar(ext_i2c_right)'; + var code = 'ext_sonar_right.value()'; + } + return [code, generator.ORDER_ATOMIC]; + } +} + +export const robot_sonar_extern_led = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var mode = this.getFieldValue('mode'); + var light = generator.valueToCode(this, 'light', generator.ORDER_ATOMIC); + var op = generator.valueToCode(this, 'bright', generator.ORDER_ATOMIC); + if (version == 'mixbot') { + generator.definitions_['import_mixbot_ext_ext_sonar'] = 'from mixbot_ext import ext_sonar'; + var code = 'ext_sonar.led(' + mode + ', ' + light + ', ' + op + ")\n"; + return code; + } else if (version == 'feiyi') { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_i2cdevice'] = 'import i2cdevice'; + if (mode == "0") { + generator.definitions_['import_left_ext_i2c'] = 'ext_i2c_left = i2cdevice.I2C_device(scl=machine.Pin(0), sda=machine.Pin(1), freq=10000)'; + generator.definitions_['import_left_sonar'] = 'ext_sonar_left = i2cdevice.Sonar(ext_i2c_left)'; + var code = 'ext_sonar_left.led(0, ' + light + ', ' + op + ')\n'; + } else if (mode == "1") { + generator.definitions_['import_right_ext_i2c'] = 'ext_i2c_right = i2cdevice.I2C_device(scl=machine.Pin(2), sda=machine.Pin(3), freq=10000)'; + generator.definitions_['import_right_sonar'] = 'ext_sonar_right = i2cdevice.Sonar(ext_i2c_right)'; + var code = 'ext_sonar_right.led(0, ' + light + ', ' + op + ')\n'; + } + return code; + } +} + +export const mixbot_sensor_extern_get_addr = function (_, generator) { + var name = this.getFieldValue('name'); + generator.definitions_['import_mixbot_ext_' + name] = 'from mixbot_ext import ' + name; + var code = name + '.addr_get()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const mixbot_sensor_extern_set_addr = function (_, generator) { + var name = this.getFieldValue('name'); + generator.definitions_['import_mixbot_ext_' + name] = 'from mixbot_ext import ' + name; + var oldaddr = generator.valueToCode(this, 'old', generator.ORDER_ATOMIC); + var newaddr = generator.valueToCode(this, 'new', generator.ORDER_ATOMIC); + var code = name + '.addr_set(' + oldaddr + ', ' + newaddr + ')\n'; + return code; +} + +export const sensor_weather_solo_init = function (_, generator) { + generator.definitions_['import_ws_solo'] = 'import ws_solo'; + var wd = generator.valueToCode(this, 'wd', generator.ORDER_ATOMIC); + var ws = generator.valueToCode(this, 'ws', generator.ORDER_ATOMIC); + var rain = generator.valueToCode(this, 'rain', generator.ORDER_ATOMIC); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + ' = ws_solo.Weather_Solo(' + wd + ', ' + ws + ', ' + rain + ')\n'; + return code; +} + +export const sensor_weather_solo_wd = function (_, generator) { + generator.definitions_['import_ws_solo'] = 'import ws_solo'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.wind_direction()' + key + ''; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_weather_solo_ws = function (_, generator) { + generator.definitions_['import_ws_solo'] = 'import ws_solo'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.wind_speed()' + key + ''; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_weather_solo_rain = function (_, generator) { + generator.definitions_['import_ws_solo'] = 'import ws_solo'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var time = generator.valueToCode(this, 'time', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.rain_count(' + time + ')' + key + ''; + return [code, generator.ORDER_ATOMIC]; +} + + +export const sensor_DS18X20 = function (_, generator) { + generator.definitions_['import_DS18X20'] = 'from ds18b20 import DS18X20'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'DS18X20(' + dropdown_pin + ').temperature()'; + return [code, generator.ORDER_ATOMIC]; +}; + +//educore sensor_extern +export const educore_body_sensor = function (_, generator) { + generator.definitions_['import_educore_tsd'] = 'from educore import tsd'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'tsd(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_soilhum_sensor = function (_, generator) { + generator.definitions_['import_educore_solihum'] = 'from educore import soilhum'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'soilhum(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_temphum_sensor = function (_, generator) { + generator.definitions_['import_educore_dht'] = 'from educore import dht'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'dht(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_infrared_sensor = function (_, generator) { + generator.definitions_['import_educore_tsd'] = 'from educore import tsd'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'tsd(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_button_sensor_extern = function (_, generator) { + generator.definitions_['import_educore_button'] = 'from educore import button'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'button(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_read_humiture = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + ".read()[" + key + "]"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_ultrasonic_sensor = function (_, generator) { + generator.definitions_['import_educore_ultrasonic'] = 'from educore import ultrasonic'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'ultrasonic(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const ultrasonic_sensor_read_distance = function (_, generator) { + generator.definitions_['import_educore_ultrasonic'] = 'from educore import ultrasonic'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + ".diatance()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_temp_sensor = function (_, generator) { + generator.definitions_['import_educore_ds18b20'] = 'from educore import ds18b20'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'ds18b20(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_camera_sensor = function (_, generator) { + generator.definitions_['import_educore_smartcamera'] = 'from educore import smartcamera'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'smartcamera(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const camera_sensor_init = function (_, generator) { + generator.definitions_['import_educore_smartcamera'] = 'from educore import smartcamera'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.init(' + key + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const camera_sensor_result = function (_, generator) { + generator.definitions_['import_educore_smartcamera'] = 'from educore import smartcamera'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.result()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_weigh_init = function (_, generator) { + generator.definitions_['import_hx270'] = 'import hx720'; + var sck = generator.valueToCode(this, 'sck', generator.ORDER_ATOMIC); + var dat = generator.valueToCode(this, 'dat', generator.ORDER_ATOMIC); + var pc = generator.valueToCode(this, 'pc', generator.ORDER_ATOMIC); + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + ' = hx720.HX720(' + sck + ', ' + dat + ', ' + pc + ')\n'; + return code; +} + +export const weigh_sensor_get_weight = function (_, generator) { + generator.definitions_['import_hx270'] = 'import hx720'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = v + ".read_weight(10)"; + return [code, generator.ORDER_ATOMIC]; +} + +export const line_tube_foot = function (_, generator) { + generator.definitions_['import_machine_Pin'] = "from machine import Pin"; + generator.definitions_['import_keypad_Keypad'] = "from keypad import Keypad"; + var pin1 = generator.valueToCode(this, 'PIN1', generator.ORDER_ATOMIC); + var pin2 = generator.valueToCode(this, 'PIN2', generator.ORDER_ATOMIC); + var pin3 = generator.valueToCode(this, 'PIN3', generator.ORDER_ATOMIC); + var pin4 = generator.valueToCode(this, 'PIN4', generator.ORDER_ATOMIC); + var code = '[Pin(' + pin1 +'),Pin(' + pin2 +'),Pin(' + pin3 +'),Pin(' + pin4 +')]'; + return [code, generator.ORDER_ATOMIC]; +} + +export const column_tube_foot = function (_, generator) { + generator.definitions_['import_machine_Pin'] = "from machine import Pin"; + generator.definitions_['import_keypad_Keypad'] = "from keypad import Keypad"; + var pin1 = generator.valueToCode(this, 'PIN1', generator.ORDER_ATOMIC); + var pin2 = generator.valueToCode(this, 'PIN2', generator.ORDER_ATOMIC); + var pin3 = generator.valueToCode(this, 'PIN3', generator.ORDER_ATOMIC); + var pin4 = generator.valueToCode(this, 'PIN4', generator.ORDER_ATOMIC); + var code = '[Pin(' + pin1 +'),Pin(' + pin2 +'),Pin(' + pin3 +'),Pin(' + pin4 +')]'; + return [code, generator.ORDER_ATOMIC]; +} + +export const define_keyboards = function (_, generator) { + generator.definitions_['import_machine_Pin'] = "from machine import Pin"; + generator.definitions_['import_keypad_Keypad'] = "from keypad import Keypad"; + var var1 = this.getFieldValue('VAR1'); + var var2 = this.getFieldValue('VAR2'); + var var3 = this.getFieldValue('VAR3'); + var var4 = this.getFieldValue('VAR4'); + var var5 = this.getFieldValue('VAR5'); + var var6 = this.getFieldValue('VAR6'); + var var7 = this.getFieldValue('VAR7'); + var var8 = this.getFieldValue('VAR8'); + var var9 = this.getFieldValue('VAR9'); + var var10 = this.getFieldValue('VAR10'); + var var11 = this.getFieldValue('VAR11'); + var var12 = this.getFieldValue('VAR12'); + var var13 = this.getFieldValue('VAR13'); + var var14 = this.getFieldValue('VAR14'); + var var15 = this.getFieldValue('VAR15'); + var var16 = this.getFieldValue('VAR16'); + var code = "[\n['"+var1+"','"+var2+"','"+var3+"','"+var4+"'],\n['"+var5+"','"+var6+"','"+var7+"','"+var8+"'],\n['"+var9+"','"+var10+"','"+var11+"','"+var12+"'],\n['"+var13+"','"+var14+"','"+var15+"','"+var16+"']]" + return [code, generator.ORDER_ATOMIC]; +} + +export const init_matrix_keyboard = function (_, generator) { + generator.definitions_['import_machine_Pin'] = "from machine import Pin"; + generator.definitions_['import_keypad_Keypad'] = "from keypad import Keypad"; + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument1 = generator.valueToCode(this, 'VALUE1', + generator.ORDER_ASSIGNMENT) || 'None'; + var argument2 = generator.valueToCode(this, 'VALUE2', + generator.ORDER_ASSIGNMENT) || 'None'; + var argument3 = generator.valueToCode(this, 'VALUE3', + generator.ORDER_ASSIGNMENT) || 'None'; + var code = varName +'= Keypad('+ argument1 +','+argument2+','+argument3+')' + return code; +} + +export const get_keboards_value = function (_, generator) { + generator.definitions_['import_machine_Pin'] = "from machine import Pin"; + generator.definitions_['import_keypad_Keypad'] = "from keypad import Keypad"; + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var code = varName + '.read_keypad()' + return [code, generator.ORDER_ATOMIC]; +} + +export const init_init_rotary_encoder = function (_, generator) { + generator.definitions_['import_rotary'] = 'import rotary'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var p1 = generator.valueToCode(this, 'PIN1', generator.ORDER_ATOMIC); + var p2 = generator.valueToCode(this, 'PIN2', generator.ORDER_ATOMIC); + var key = generator.valueToCode(this, 'KEY', generator.ORDER_ATOMIC); + var m = generator.valueToCode(this, 'METHOD', generator.ORDER_ATOMIC); + var code = v + " = rotary.Encoder("+ p1 +","+ p2 +","+ key +","+ m +")\n"; + return code; +} + +export const rotary_key = function (_, generator) { + generator.definitions_['import_rotary'] = 'import rotary'; + var key = this.getFieldValue("key"); + var code = 'rotary.'+ key ; + return [code,generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/sensor_onboard.js b/mixly/boards/default_src/micropython/generators/sensor_onboard.js new file mode 100644 index 00000000..291669da --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/sensor_onboard.js @@ -0,0 +1,978 @@ +import { Boards } from 'mixly'; +import { sensor_dht11 } from './sensor_extern.js'; + +export const sensor_mixgo_button_is_pressed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var code = version + '.' + btn + '.is_pressed()'; + return [code, generator.ORDER_ATOMIC]; +} + +//ok +export const sensor_mixgo_button_was_pressed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var code = version + '.' + btn + '.was_pressed()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_button_get_presses = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = version + '.' + btn + '.get_presses(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_button_attachInterrupt = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var dropdown_btn = generator.valueToCode(this, 'btn', generator.ORDER_ATOMIC); + var dropdown_mode = this.getFieldValue('mode'); + var atta = generator.valueToCode(this, 'DO', generator.ORDER_ATOMIC); + var code = version + '.' + dropdown_btn + '.irq' + '(handler=' + atta + ', trigger=' + dropdown_mode + ')\n' + return code; +} + +//ok +export const sensor_mixgocar42_button_is_pressed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var code = version + '.' + 'button.is_pressed()'; + return [code, generator.ORDER_ATOMIC]; +} + +//ok +export const sensor_mixgocar42_button_was_pressed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var code = version + '.' + 'button.was_pressed()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgocar42_button_get_presses = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = version + '.' + 'button.get_presses(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgocar42_button_attachInterrupt = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version] = 'import ' + version; + var dropdown_mode = this.getFieldValue('mode'); + var atta = generator.valueToCode(this, 'DO', generator.ORDER_ATOMIC); + var code = version + '.' + 'button.irq' + '(handler=' + atta + ', trigger=' + dropdown_mode + ')\n' + return code; +} + +export const HCSR04 = function (_, generator) { + generator.definitions_['import_sonar'] = 'import sonar'; + var dropdown_pin1 = generator.valueToCode(this, "PIN1", generator.ORDER_ASSIGNMENT); + var dropdown_pin2 = generator.valueToCode(this, "PIN2", generator.ORDER_ASSIGNMENT); + var code = 'sonar.Sonar(' + dropdown_pin1 + ', ' + dropdown_pin2 + ').checkdist()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const number1 = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const number2 = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const number3 = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const number4 = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const number5 = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const number6 = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const number7 = function (_, generator) { + var code = this.getFieldValue('op'); + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_pin_near_single = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_als'] = "from " + version + " import onboard_als"; + var code = 'onboard_als.ps_nl()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_pin_near_double = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version] = 'import ' + version; + var direction = this.getFieldValue('direction'); + var code = version + '.' + 'infrared_' + direction + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_pin_near = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_als'] = 'from ' + version + ' import onboard_als'; + var code = 'onboard_als.ps()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_nova_pin_near = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var direction = this.getFieldValue('direction'); + generator.definitions_['import_' + version + '_' + direction] = 'from ' + version + ' import onboard_als_' + direction; + var code = 'onboard_als_' + direction + '.ps_nl()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_LTR308 = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_als'] = 'from ' + version + ' import onboard_als'; + var code = 'onboard_als.als()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_sant_color = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_als'] = 'from ' + version + ' import onboard_als'; + var code = 'onboard_als.color()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_nova_LTR308 = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var direction = this.getFieldValue('direction'); + generator.definitions_['import_' + version + '_' + direction] = 'from ' + version + ' import onboard_als_' + direction; + var code = 'onboard_als_' + direction + '.als_vis()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_ds18x20 = function (_, generator) { + generator.definitions_['import_ds18x20x'] = 'import ds18x20x'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'ds18x20x.get_ds18x20_temperature(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_lm35 = function (_, generator) { + generator.definitions_['import_lm35'] = 'import lm35'; + var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'lm35.get_LM35_temperature(' + dropdown_pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_LTR308 = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == "mixgo") { + generator.definitions_['import_mixgo'] = 'import mixgo'; + return ['mixgo.get_brightness()', generator.ORDER_ATOMIC]; + } else if (version == "mixgo_ce") { + generator.definitions_['import_mixgo_ce'] = 'import mixgo_ce'; + return ['mixgo_ce.get_brightness()', generator.ORDER_ATOMIC]; + } else if (version == "mpython") { + generator.definitions_['import_mpython_onboard_light'] = 'from mpython import onboard_light'; + return ['onboard_light.brightness()', generator.ORDER_ATOMIC]; + } + generator.definitions_['import_' + version + '_onboard_als'] = "from " + version + " import onboard_als"; + var code = 'onboard_als.als_vis()'; + return [code, generator.ORDER_ATOMIC]; + // else{return ['', generator.ORDER_ATOMIC];} +} + +export const sensor_sound = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixbot') { + generator.definitions_['import_' + version + '_sound'] = 'from ' + version + ' import sound'; + var code = 'sound.loudness()'; + } else if (version == 'mixgo_zero') { + generator.definitions_['import_mixgo_zero_voice_sound_level'] = "from mixgo_zero_voice import sound_level"; + var code = 'sound_level()'; + } else if (version == 'mixgo_nova') { + generator.definitions_['import_mixgo_nova_voice_sound_level'] = "from mixgo_nova_voice import sound_level"; + var code = 'sound_level()'; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_mixgo_soar_voice_sound_level'] = "from mixgo_soar_voice import sound_level"; + var code = 'sound_level()'; + }else if (version == "mixgo") { + generator.definitions_['import_mixgo'] = 'import mixgo'; + return ['mixgo.get_soundlevel()', generator.ORDER_ATOMIC]; + } else if (version == "mpython") { + generator.definitions_['import_mpython_onboard_sound'] = 'from mpython import onboard_sound'; + return ['onboard_sound.soundlevel()', generator.ORDER_ATOMIC]; + } else if (version == "mixgo_mini") { + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.soundlevel()'; + } else { + generator.definitions_['import_' + version + '_onboard_sound'] = 'from ' + version + ' import onboard_sound'; + var code = 'onboard_sound.read()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +// export const sensor_mixgo_nova_sound = function (_, generator) { +// var version = Boards.getSelectedBoardKey().split(':')[2] +// return [code, generator.ORDER_ATOMIC]; +// } + +export const sensor_hp203 = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var key = this.getFieldValue('key'); + if (version == "mixgo_mini") { + generator.definitions_['import_mixgo_mini_onboard_i2c'] = 'from mixgo_mini import onboard_i2c'; + generator.definitions_['import_spl06_001'] = 'import spl06_001'; + generator.definitions_['import_onboard_bps'] = 'onboard_bps = spl06_001.SPL06(onboard_i2c)'; + } else { + generator.definitions_['import_' + version + '_onboard_bps'] = "from " + version + " import onboard_bps"; + } + var code = 'onboard_bps.' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_aht11 = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var key = this.getFieldValue('key'); + if (version == 'mixgo_nova' || version == 'mixgo_zero') { + generator.definitions_['import_' + version + '_onboard_ths'] = "from " + version + " import onboard_ths"; + } else if (version == 'mixgo_mini') { + generator.definitions_['import_mixgo_mini_onboard_i2c'] = 'from mixgo_mini import onboard_i2c'; + generator.definitions_['import_shtc3'] = 'import shtc3'; + generator.definitions_['import_onboard_ths'] = 'onboard_ths = shtc3.SHTC3(onboard_i2c)'; + } else { + generator.definitions_['import_' + version + '_onboard_ths'] = "from " + version + " import onboard_ths"; + } + var code = 'onboard_ths.' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_get_temperature = function (_, generator) { + generator.definitions_['import_feiyi_onboard_acc'] = 'from feiyi import onboard_acc'; + return ['onboard_acc.temperature()', generator.ORDER_ATOMIC]; +} + +export const rfid_readid = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var moduleName = version; + var objName = 'onboard_rfid'; + if (version === 'mixgo_mini') { + moduleName = 'mini_gx'; + objName = 'ext_rfid'; + } else if (version === 'mixgo_me') { + moduleName = 'me_g1'; + objName = 'ext_rc522'; + }else if (version === 'mixgo_sant'){ + moduleName = 'sant_gx'; + objName = 'ext_rfid'; + } + generator.definitions_[`import_${moduleName}_${objName}`] = `from ${moduleName} import ${objName}`; + var code = `${objName}.read_card(0, x="id")`; + return [code, generator.ORDER_ATOMIC]; +} + +export const rfid_readcontent = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var sector = generator.valueToCode(this, 'SECTOR', generator.ORDER_ATOMIC); + var moduleName = version; + var objName = 'onboard_rfid'; + if (version === 'mixgo_mini') { + moduleName = 'mini_gx'; + objName = 'ext_rfid'; + } else if (version === 'mixgo_me') { + moduleName = 'me_g1'; + objName = 'ext_rc522'; + }else if (version === 'mixgo_sant'){ + moduleName = 'sant_gx'; + objName = 'ext_rfid'; + } + generator.definitions_[`import_${moduleName}_${objName}`] = `from ${moduleName} import ${objName}`; + var code = `${objName}.read_card(${sector}, x="content")`; + return [code, generator.ORDER_ATOMIC]; +} + +export const rfid_write = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var sector = generator.valueToCode(this, 'SECTOR', generator.ORDER_ATOMIC); + var cnt = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC); + var moduleName = version; + var objName = 'onboard_rfid'; + if (version === 'mixgo_mini') { + moduleName = 'mini_gx'; + objName = 'ext_rfid'; + } else if (version === 'mixgo_me') { + moduleName = 'me_g1'; + objName = 'ext_rc522'; + }else if (version === 'mixgo_sant'){ + moduleName = 'sant_gx'; + objName = 'ext_rfid'; + } + generator.definitions_[`import_${moduleName}_${objName}`] = `from ${moduleName} import ${objName}`; + var code = `${objName}.write_card(${cnt}, ${sector})\n`; + return code; +} + +export const rfid_write_return = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var sector = generator.valueToCode(this, 'SECTOR', generator.ORDER_ATOMIC); + var cnt = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC); + var moduleName = version; + var objName = 'onboard_rfid'; + if (version === 'mixgo_mini') { + moduleName = 'mini_gx'; + objName = 'ext_rfid'; + } else if (version === 'mixgo_me') { + moduleName = 'me_g1'; + objName = 'ext_rc522'; + }else if (version === 'mixgo_sant'){ + moduleName = 'sant_gx'; + objName = 'ext_rfid'; + } + generator.definitions_[`import_${moduleName}_${objName}`] = `from ${moduleName} import ${objName}`; + var code = `${objName}.write_card(${cnt}, ${sector})`; + return [code, generator.ORDER_ATOMIC]; +} + +export const rfid_status = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var key = this.getFieldValue('key'); + var moduleName = version; + var objName = 'onboard_rfid'; + if (version === 'mixgo_mini') { + moduleName = 'mini_gx'; + objName = 'ext_rfid'; + } else if (version === 'mixgo_me') { + moduleName = 'me_g1'; + objName = 'ext_rc522'; + } else if (version === 'mixgo_sant'){ + moduleName = 'sant_gx'; + objName = 'ext_rfid'; + } + generator.definitions_[`import_${moduleName}_${objName}`] = `from ${moduleName} import ${objName}`; + var code = `${objName}.scan_card() == ${key}`; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_get_acceleration = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var key = this.getFieldValue('key'); + if (key == 'strength') { + if (version == 'mixbot') { + generator.definitions_['import_' + version + '_acc_gyr'] = 'from ' + version + ' import acc_gyr'; + var code = 'acc_gyr.strength()'; + } else if(version == 'mixgo_soar'){ + generator.definitions_['import_' + version + '_onboard_imu'] = "from " + version + " import onboard_imu"; + var code = 'onboard_imu.strength()'; + } else { + generator.definitions_['import_' + version + '_onboard_acc'] = "from " + version + " import onboard_acc"; + var code = 'onboard_acc.strength()'; + } + return [code, generator.ORDER_ATOMIC]; + } + if (version == 'mixbot') { + generator.definitions_['import_' + version + '_acc_gyr'] = 'from ' + version + ' import acc_gyr'; + var code = 'acc_gyr.accelerometer()' + key; + } else if (version == 'mpython') { + generator.definitions_['import_mpython_motion'] = 'from mpython import motion'; + var code = 'motion.accelerometer()' + key; + } else if (version == 'mixgo_soar') { + generator.definitions_['import_' + version + '_onboard_imu'] = "from " + version + " import onboard_imu"; + var code = 'onboard_imu.acceleration()'+ key; + }else { + generator.definitions_['import_' + version + '_onboard_acc'] = "from " + version + " import onboard_acc"; + var code = 'onboard_acc.acceleration()' + key; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_eulerangles = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_acc'] = "from " + version + " import onboard_acc"; + var angle = this.getFieldValue('angle'); + var code = 'onboard_acc.eulerangles()' + angle; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_gesture = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var gesture = this.getFieldValue('gesture'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_is_gesture("' + gesture + '")'; + return [code, generator.ORDER_ATOMIC]; +} + +//ok +export const sensor_mpu9250_get_acceleration = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_get_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgoce_pin_pressed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var pin = generator.valueToCode(this, 'button', generator.ORDER_ATOMIC); + if (version === 'mixgo_mini' || version === 'mixgo_sant' || version === 'mixgo_soar') { + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.touched(' + pin + ')'; + } else { + generator.definitions_['import_' + version] = 'import ' + version; + var code = version + '.touched(' + pin + ')'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_touch_slide = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version === 'mixgo_mini' || version === 'mixgo_sant' || version === 'mixgo_soar' || version === 'mixgo_sowl') { + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.touch_slide()'; + } else { + generator.definitions_['import_' + version] = 'import ' + version; + var code = version + '.touch_slide(3, 4)'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_pin_pressed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version] = 'import ' + version; + var pin = generator.valueToCode(this, 'button', generator.ORDER_ATOMIC); + var code = version + '.' + pin + '.is_touched()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpython_pin_pressed = function (_, generator) { + generator.definitions_['import_mpython'] = 'import mpython'; + var pin = generator.valueToCode(this, 'button', generator.ORDER_ATOMIC); + var code = 'mpython.touch_' + pin + '.is_touched()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_adxl345_get_acceleration = function (_, generator) { + generator.definitions_['import_adxl345'] = 'import adxl345'; + // generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code; + if (key == 'x') { + code = v + '.readX()'; + } else if (key == 'y') { + code = v + '.readY()'; + } else if (key == 'z') { + code = v + '.readZ()'; + } else if (key == 'values') { + code = v + '.readXYZ()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_get_magnetic = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_magnetic_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_get_gyro = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + var code = v + '.mpu9250_gyro_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_calibrate_compass = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_compass'] = 'from mixgo import compass'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + return '' + v + '.calibrate()\n'; +} + +export const sensor_mpu9250_temperature = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "mpu") + generator.definitions_['import_mixgo_mpu'] = 'from mixgo import mpu'; + return [v + '.mpu9250_get_temperature()', generator.ORDER_ATOMIC]; +} + +export const sensor_mpu9250_field_strength = function (_, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + if (v == "compass") + generator.definitions_['import_mixgo_compass'] = 'from mixgo import compass'; + var compass = this.getFieldValue('compass'); + var a; + if (compass == 'strength') { + a = v + '.get_field_strength()'; + } else if (compass == 'heading') { + a = v + '.heading()'; + } + return [a, generator.ORDER_ATOMIC]; +} + +export const sensor_compass_reset = function (block, generator) { + generator.definitions_['import_mpu9250'] = 'import mpu9250'; + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_compass'] = 'from mixgo import compass'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + return '' + v + '.reset_calibrate()\n'; +} + +export const sensor_onboard_mpu9250_gesture = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var gesture = this.getFieldValue('gesture'); + generator.definitions_['import_mixgo_onboard_mpu'] = 'from mixgo import onboard_mpu'; + var code = 'onboard_mpu.mpu9250_is_gesture("' + gesture + '")'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_onboard_mpu9250_get_acceleration = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + generator.definitions_['import_mixgo_onboard_mpu'] = 'from mixgo import onboard_mpu'; + var code = 'onboard_mpu.mpu9250_get_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_onboard_mpu9250_get_magnetic = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + generator.definitions_['import_mixgo_onboard_mpu'] = 'from mixgo import onboard_mpu'; + var code = 'onboard_mpu.mpu9250_magnetic_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_onboard_mpu9250_get_gyro = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var key = this.getFieldValue('key'); + generator.definitions_['import_mixgo_onboard_mpu'] = 'from mixgo import onboard_mpu'; + var code = 'onboard_mpu.mpu9250_gyro_' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_onboard_mpu9250_calibrate_compass = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_onboard_compass'] = 'from mixgo import onboard_compass'; + return '' + 'onboard_compass.calibrate()\n'; +} + +export const sensor_onboard_mpu9250_temperature = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_onboard_mpu'] = 'from mixgo import onboard_mpu'; + return ['onboard_mpu.mpu9250_get_temperature()', generator.ORDER_ATOMIC]; +} + +export const sensor_onboard_mpu9250_field_strength = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_onboard_compass'] = 'from mixgo import onboard_compass'; + var compass = this.getFieldValue('compass'); + var a; + if (compass == 'strength') { + a = 'onboard_compass.get_field_strength()'; + } else if (compass == 'heading') { + a = 'onboard_compass.heading()'; + } + return [a, generator.ORDER_ATOMIC]; +} + +export const sensor_onboard_compass_reset = function (block, generator) { + generator.definitions_['import_machine'] = 'import machine'; + generator.definitions_['import_mixgo_onboard_compass'] = 'from mixgo import onboard_compass'; + return '' + 'onboard_compass.reset_calibrate()\n'; +} + +export const onboard_RTC_set_datetime = function (_, generator) { + generator.definitions_['import_rtctime'] = "import rtctime"; + var year = generator.valueToCode(this, "year", generator.ORDER_ASSIGNMENT); + var month = generator.valueToCode(this, "month", generator.ORDER_ASSIGNMENT); + var day = generator.valueToCode(this, "day", generator.ORDER_ASSIGNMENT); + var hour = generator.valueToCode(this, "hour", generator.ORDER_ASSIGNMENT); + var minute = generator.valueToCode(this, "minute", generator.ORDER_ASSIGNMENT); + var second = generator.valueToCode(this, "second", generator.ORDER_ASSIGNMENT); + var code = 'rtctime.settime((' + year + ', ' + month + ', ' + day + ', ' + hour + ', ' + minute + ', ' + second + ', 0, 0))\n'; + return code; +} + +export const onboard_RTC_settime_string = function (_, generator) { + var cnt = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC); + generator.definitions_['import_rtctime'] = "import rtctime"; + var code = 'rtctime.settime(' + cnt + ')\n'; + return code; +} + +export const onboard_RTC_get_time = function (_, generator) { + generator.definitions_['import_time'] = 'import time'; + var code = 'time.localtime()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const onboard_RTC_get_timestamp = function (_, generator) { + generator.definitions_['import_time'] = 'import time'; + var time = generator.valueToCode(this, 'LIST', generator.ORDER_ATOMIC); + var code = 'time.mktime(' + time + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const onboard_RTC_timestamp_totuple = function (_, generator) { + generator.definitions_['import_time'] = 'import time'; + var ts = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = 'time.localtime(' + ts + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const onboard_RTC_get_time_str = function (_, generator) { + generator.definitions_['import_rtctime'] = 'import rtctime'; + var code = 'rtctime.strtime()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const onboard_RTC_get_timetuple_to_str = function (_, generator) { + generator.definitions_['import_rtctime'] = 'import rtctime'; + var ct = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC); + var code = 'rtctime.strtime(' + ct + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +//mixgo_cc onboard_sensor generators: + +export const sensor_mixgo_cc_mmc5603_get_magnetic = function (_, generator) { + var key = this.getFieldValue('key'); + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mpython') { + generator.definitions_['import_mpython_magnetic'] = 'from mpython import magnetic'; + if (key == 'all') { + var code = 'magnetic.getstrength()'; + } else { + var code = 'magnetic.getdata()' + key; + } + } else if (version == 'mixgo_mini') { + generator.definitions_['import_mixgo_mini_onboard_i2c'] = 'from mixgo_mini import onboard_i2c'; + generator.definitions_['import_mmc5603'] = 'import mmc5603'; + generator.definitions_['import_onboard_mgs'] = 'onboard_mgs = mmc5603.MMC5603(onboard_i2c)'; + if (key == 'all') { + var code = 'onboard_mgs.getstrength()'; + } else { + var code = 'onboard_mgs.getdata()' + key; + } + } else { + generator.definitions_['import_' + version + '_onboard_mgs'] = "from " + version + " import onboard_mgs"; + if (key == 'all') { + var code = 'onboard_mgs.getstrength()'; + } else { + var code = 'onboard_mgs.getdata()' + key; + } + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_cc_mmc5603_get_angle = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mpython') { + generator.definitions_['import_mpython_magnetic'] = 'from mpython import magnetic'; + var code = 'magnetic.getangle()'; + } else if (version == 'mixgo_mini') { + generator.definitions_['import_mixgo_mini_onboard_i2c'] = 'from mixgo_mini import onboard_i2c'; + generator.definitions_['import_mmc5603'] = 'import mmc5603'; + generator.definitions_['import_onboard_mgs'] = 'onboard_mgs = mmc5603.MMC5603(onboard_i2c)'; + } else { + generator.definitions_['import_' + version + '_onboard_mgs'] = "from " + version + " import onboard_mgs"; + } + var code = 'onboard_mgs.getangle()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgo_cc_mmc5603_calibrate_compass = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_mini') { + generator.definitions_['import_mixgo_mini_onboard_i2c'] = 'from mixgo_mini import onboard_i2c'; + generator.definitions_['import_mmc5603'] = 'import mmc5603'; + generator.definitions_['import_onboard_mgs'] = 'onboard_mgs = mmc5603.MMC5603(onboard_i2c)'; + } else { + generator.definitions_['import_' + version + '_onboard_mgs'] = "from " + version + " import onboard_mgs"; + } + var code = 'onboard_mgs.calibrate()\n'; + return code; +} + +//mixgo_me onboard_sensor generators: + +export const sensor_mixgome_temperature = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'mixgo_mini') { + generator.definitions_['import_mixgo_mini_onboard_temperature'] = 'from mixgo_mini import onboard_temperature'; + var code = 'onboard_temperature()'; + } else { + generator.definitions_['import_mixgo_me_onboard_acc'] = "from mixgo_me import onboard_acc"; + var code = 'onboard_acc.temperature()'; + } + return [code, generator.ORDER_ATOMIC]; +} + +//mixgo_ce onboard_sensor generators: +export const sensor_mixgoce_temperature = function (_, generator) { + generator.definitions_['import_mixgo_ce'] = "import mixgo_ce"; + var code = 'mixgo_ce.get_temperature()'; + return [code, generator.ORDER_ATOMIC]; +} + +//mpython onboard_sensor: + +export const sensor_mpython_qmi8658_get_gyro = function (_, generator) { + var key = this.getFieldValue('key'); + generator.definitions_['import_mpython_motion'] = 'from mpython import motion'; + var code = 'motion.gyroscope()' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mpython_qmi8658_temperature = function (_, generator) { + generator.definitions_['import_mpython_motion'] = 'from mpython import motion'; + return ['motion.temperature()', generator.ORDER_ATOMIC]; +} + +export const sensor_rm_pin_near_double = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var direction = this.getFieldValue('direction'); + generator.definitions_['import_' + version + '_adc' + direction] = 'from ' + version + ' import adc' + direction; + var code = 'adc' + direction + '.read()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_rm_battery_left = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + if (version == 'feiyi') { + generator.definitions_['import_feiyi_onboard_bot51'] = 'from feiyi import onboard_bot51'; + var code = 'onboard_bot51.read_bat()'; + return [code, generator.ORDER_ATOMIC]; + } + generator.definitions_['import_' + version + '_battery'] = 'from ' + version + ' import battery'; + var code = 'battery.voltage()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_rm_acc = function (_, generator) { + var key = this.getFieldValue('key'); + generator.definitions_['import_rm_e1_gyro'] = 'from rm_e1 import gyro'; + var code = 'gyro.acceleration()' + key; + return [code, generator.ORDER_ATOMIC]; +} + +//car4.2 +export const sensor_mixgocar_pin_near_line = function (_, generator) { + var key = this.getFieldValue('key'); + generator.definitions_['import_mixgocar_c3_onboard_info'] = 'from mixgocar_c3 import onboard_info'; + var code = 'onboard_info.patrol()' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgocar_pin_near = function (_, generator) { + var key = this.getFieldValue('key'); + generator.definitions_['import_mixgocar_c3_onboard_info'] = 'from mixgocar_c3 import onboard_info'; + var code = 'onboard_info.obstacle()' + key; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixgocar_pin_near_state_change = function (_, generator) { + var key = this.getFieldValue('key'); + generator.definitions_['import_mixgocar_c3_onboard_info'] = 'from mixgocar_c3 import onboard_info'; + var code = 'onboard_info.ir_mode(onboard_info.' + key + ')\n'; + return code; +} + +export const sensor_mixgocar_battery_left = function (_, generator) { + generator.definitions_['import_mixgocar_c3_onboard_info'] = 'from mixgocar_c3 import onboard_info'; + var code = 'onboard_info.read_bat()'; + return [code, generator.ORDER_ATOMIC]; +} + +//mixbot onboard_sensor below: + +export const sensor_mixbot_patrol_calibrate = function (_, generator) { + var key = this.getFieldValue('key'); + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_patrol'] = 'from ' + version + ' import patrol'; + var code = 'patrol.correct(patrol.CORRECTING_' + key + ')\n'; + return code; +} + +export const sensor_mixbot_patrol_value = function (_, generator) { + var key = this.getFieldValue('key'); + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_patrol'] = 'from ' + version + ' import patrol'; + var code = 'patrol.getdata()' + key + ''; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixbot_temperature = function (_, generator) { + generator.definitions_['import_mixbot_acc_gyr'] = "from mixbot import acc_gyr"; + var code = 'acc_gyr.temperature()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_mixbot_get_gyro = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + var key = this.getFieldValue('key'); + if(version == 'mixgo_soar'){ + generator.definitions_['import_' + version + '_onboard_imu'] = "from " + version + " import onboard_imu"; + var code = 'onboard_imu.gyroscope()' +key ; + }else{ + generator.definitions_['import_mixbot_acc_gyr'] = "from mixbot import acc_gyr"; + var code = 'acc_gyr.gyroscope()' + key; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_bitbot_ALS = function (_, generator) { + generator.definitions_['import_feiyi_onboard_bot51'] = 'from feiyi import onboard_bot51'; + var mode = generator.valueToCode(this, 'mode', generator.ORDER_ATOMIC); + var code = 'onboard_bot51.' + 'read_als(' + mode + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const bitbot_als_num = function (_, generator) { + var code = this.getFieldValue('PIN'); + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_button_is_pressed = sensor_mixgo_button_is_pressed; +export const sensor_button_was_pressed = sensor_mixgo_button_was_pressed; +export const sensor_button_get_presses = sensor_mixgo_button_get_presses; +export const sensor_pin_pressed = sensor_mixgo_pin_pressed; +export const sensor_pin_near = sensor_mixgo_pin_near; +export const sensor_mixgo_light = sensor_LTR308; +export const sensor_light = sensor_mixgo_light; +export const dht11 = sensor_dht11; + +//educore onboard_sensor +export const educore_voice_sensor = function (_, generator) { + generator.definitions_['import_educore_sound'] = 'from educore import sound'; + var code = "sound()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_read = function (_, generator) { + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + ".read()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_light_sensor = function (_, generator) { + generator.definitions_['import_educore_light'] = 'from educore import light'; + var code = "light()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_gyroscope_sensor = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_accelerometer'] = 'from ' + version + ' import accelerometer'; + var code = "accelerometer()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_gyroscope_sensor_read = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_accelerometer'] = 'from ' + version + ' import accelerometer'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + "." + key + "()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_gyroscope_sensor_shake = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_accelerometer'] = 'from ' + version + ' import accelerometer'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + ".shake()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_button_sensor = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_button'] = 'from ' + version + ' import button'; + var btn = this.getFieldValue('btn'); + var code = 'button(button.' + btn + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_button_was_pressed = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_button'] = 'from ' + version + ' import button'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.status()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_rfid_sensor = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_rfid'] = 'from ' + version + ' import rfid'; + var pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC); + var code = 'rfid(' + pin + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_rfid_sensor_scan = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_rfid'] = 'from ' + version + ' import rfid'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var code = sub + '.scanning()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const educore_rfid_sensor_scan_data = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_rfid'] = 'from ' + version + ' import rfid'; + var sub = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var key = this.getFieldValue('key'); + var code = sub + '.' + key + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const sensor_get_the_coprocessor_version = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var code = 'onboard_bot.version()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const simulated_light_sensor = function (_, generator){ + var version = Boards.getSelectedBoardKey().split(':')[2]; + generator.definitions_['import_' + version + '_onboard_bot'] = 'from ' + version + ' import onboard_bot'; + var key = this.getFieldValue('key'); + var code = 'onboard_bot.brightness('+ key + ')'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/serial.js b/mixly/boards/default_src/micropython/generators/serial.js new file mode 100644 index 00000000..73433cdd --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/serial.js @@ -0,0 +1,123 @@ +export const serial_print = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode'); + var content = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC) || '""' + var code = "uart" + dropdown_uart + ".write(str(" + content + "))\n"; + return code; +} + +export const serial_print_byte = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode'); + var content = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC) || '""' + var code = "uart" + dropdown_uart + ".write(" + content + ")\n"; + return code; +} + +export const serial_println = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode'); + var content = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC) || '""' + var code = "uart" + dropdown_uart + ".write(str(" + content + ")+'\\r\\n')\n"; + return code; +} + +export const serial_print_hex = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode'); + var dropdown_stat = this.getFieldValue('STAT'); + var content = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC) || '0'; + var code = "uart" + dropdown_uart + ".write(str(" + dropdown_stat + "(" + content + "))+'\\r\\n')\n"; + return code; +} + +export const serial_any = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode'); + var code = "uart" + dropdown_uart + ".any()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const serial_readstr = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode'); + var code = "uart" + dropdown_uart + ".read()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const serial_readline = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode'); + var code = "uart" + dropdown_uart + ".readline()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const serial_softserial = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var dropdown_uart = this.getFieldValue('mode') + var baudrate = this.getFieldValue('baudrate'); + return "uart" + dropdown_uart + "=machine.UART(" + dropdown_uart + ", " + baudrate + ")\n"; +} + +export const serial_softserial_new = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var rx = generator.valueToCode(this, 'RX', generator.ORDER_ATOMIC); + var tx = generator.valueToCode(this, 'TX', generator.ORDER_ATOMIC); + var dropdown_uart = this.getFieldValue('mode') + var baudrate = this.getFieldValue('baudrate'); + return "uart" + dropdown_uart + "=machine.UART(" + dropdown_uart + ", tx=" + tx + ", rx=" + rx + ", baudrate=" + baudrate + ")\n"; +} + +export const system_input = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + return ['input(' + str + ')', generator.ORDER_ATOMIC]; +} + +export const system_print = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + var code = "print(" + str + ")\n"; + return code; +} + +export const system_print_inline = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + var code = "print(" + str + ',end ="")\n'; + return code; +} + +export const system_print_end = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + var end = generator.valueToCode(this, 'END', generator.ORDER_ATOMIC) || '""'; + var code = "print(" + str + ',end =' + end + ')\n'; + return code; +} + +export const system_print_many = function (_, generator) { + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + var code = 'print(' + code.join(', ') + ')\n'; + return code; +} + +export const serial_send_to_ai = function (_, generator) { + generator.definitions_['import_uart_com'] = 'import uart_com'; + var dropdown_uart = this.getFieldValue('mode'); + var dropdown_stat = this.getFieldValue('STAT'); + var content = generator.valueToCode(this, 'CONTENT', generator.ORDER_ATOMIC) || '0'; + var code = "uart_com.send(uart" + dropdown_uart + ", " + content + ", repeat=" + dropdown_stat + ")\n"; + return code; +} + +export const serial_read_from_ai = function (_, generator) { + generator.definitions_['import_uart_com'] = 'import uart_com'; + var dropdown_uart = this.getFieldValue('mode'); + var code = "uart_com.recv(uart" + dropdown_uart + ")"; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/system.js b/mixly/boards/default_src/micropython/generators/system.js new file mode 100644 index 00000000..f4a1377e --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/system.js @@ -0,0 +1,204 @@ +import { Profile } from 'mixly'; + +export const system_run_in_background = function (_, generator) { + var branch = generator.statementToCode(this, 'do'); + return 'control.inBackground(() => {\n' + branch + '})\n'; +} + +export const system_reset = function () { + return 'control.reset()\n'; +} + +export const system_wait = function (_, generator) { + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC) || Profile.default.serial; + return 'control.waitMicros(' + data + ')\n'; +} + +export const system_raise_event = function (_, generator) { + var source = generator.valueToCode(this, 'system_event_bus_source', generator.ORDER_ATOMIC) || Profile.default.serial; + var value = generator.valueToCode(this, 'system_event_bus_value', generator.ORDER_ATOMIC) || Profile.default.serial; + return 'control.raiseEvent(' + source + ', ' + value + ')\n'; +} + +export const system_on_event = function (_, generator) { + var source = generator.valueToCode(this, 'system_event_bus_source', generator.ORDER_ATOMIC) || Profile.default.serial; + var value = generator.valueToCode(this, 'system_event_bus_value', generator.ORDER_ATOMIC) || Profile.default.serial; + var branch = generator.statementToCode(this, 'do'); + return 'control.onEvent(' + source + ', ' + value + ', () => {\n' + branch + ')\n'; +} + +export const system_timestamp = function (_, generator) { + return ['control.eventTimestamp()', generator.ORDER_ATOMIC]; +} + +export const system_value = function (_, generator) { + return ['control.eventValue()', generator.ORDER_ATOMIC]; +} + +export const system_event_bus_source = function (_, generator) { + return [this.getFieldValue('key'), generator.ORDER_ATOMIC]; +} + +export const system_event_bus_value = function (_, generator) { + return [this.getFieldValue('key'), generator.ORDER_ATOMIC]; +} + +export const system_device_name = function (_, generator) { + return ['control.deviceName()', generator.ORDER_ATOMIC]; +} + +export const system_device_serial_number = function (_, generator) { + return ['control.deviceSerialNumber()', generator.ORDER_ATOMIC]; +} + +//ok +export const Panic_with_status_code = function (_, generator) { + var status_code = generator.valueToCode(this, 'STATUS_CODE', generator.ORDER_ATOMIC) || '1000' + var code = 'panic(' + status_code + ')\n'; + return code; +} + +//ok +export const controls_millis = function (_, generator) { + generator.definitions_['import_time'] = 'import time'; + var dropdown_time = this.getFieldValue('Time'); + switch (dropdown_time) { + case "ms": + var code = 'time.ticks_ms()'; + return [code, generator.ORDER_ATOMIC]; + case "us": + var code = 'time.ticks_us()'; + return [code, generator.ORDER_ATOMIC]; + } +} + +//ok +export const controls_end_program = function () { + return 'while True:\n pass\n'; +} + +//ok +export const reset = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + return 'reset()\n'; +} + +export const controls_uname = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + return 'os.uname()'; +} + +export const controls_delay = function (_, generator) { + // generator.definitions_.import_time = "import time"; + generator.definitions_['import_time'] = 'import time'; + var delay_time = generator.valueToCode(this, 'DELAY_TIME', generator.ORDER_ATOMIC) || '1000' + var dropdown_time = this.getFieldValue('Time'); + switch (dropdown_time) { + case "s": + var code = 'time.sleep(' + delay_time + ')\n'; + return code; + case "ms": + var code = 'time.sleep_ms(' + delay_time + ')\n'; + return code; + case "us": + var code = 'time.sleep_us(' + delay_time + ')\n'; + return code; + } +} + +export const controls_delay_new = function (_, generator) { + // generator.definitions_.import_time = "import time"; + generator.definitions_['import_time'] = 'import time'; + var delay_time = generator.valueToCode(this, 'DELAY_TIME', generator.ORDER_ATOMIC) || '1000' + var dropdown_time = this.getFieldValue('Time'); + switch (dropdown_time) { + case "s": + var code = 'time.sleep(' + delay_time + ')\n'; + return code; + case "ms": + var code = 'time.sleep_ms(' + delay_time + ')\n'; + return code; + case "us": + var code = 'time.sleep_us(' + delay_time + ')\n'; + return code; + } +} + +export const timer = function (_, generator) { + generator.definitions_['import_mixgo'] = 'import mixgo'; + var v = generator.valueToCode(this, "VAR", generator.ORDER_NONE) || "None"; + var period = generator.valueToCode(this, "period", generator.ORDER_NONE) || "0"; + var mode = generator.valueToCode(this, "mode", generator.ORDER_NONE) || "None"; + var callback = generator.valueToCode(this, "callback", generator.ORDER_NONE) || "None"; + // var callback = generator.valueToCode(this, "callback", generator.ORDER_NONE) || "None"; + var code = v + ".init(period=" + period + ", mode=Timer." + mode + ", callback=" + callback + ")\n"; + return code; +} + + +export const set_system_timer = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, "VAR", generator.ORDER_NONE) || "None"; + var i = generator.valueToCode(this, "PIN", generator.ORDER_NONE) || "None"; + var period = generator.valueToCode(this, "period", generator.ORDER_NONE) || "0"; + var mode = this.getFieldValue('mode'); + var callback = generator.valueToCode(this, "callback", generator.ORDER_NONE) || "None"; + var code = v + " = machine.Timer("+ i +", period=" + period + ", mode=machine.Timer." + mode + ", callback=" + callback + ")\n"; + return code; +} + +export const system_ticks_diff = function (_, generator) { + generator.definitions_['import_time'] = 'import time'; + var end = generator.valueToCode(this, "END", generator.ORDER_NONE) || "0"; + var start = generator.valueToCode(this, "START", generator.ORDER_NONE) || "0"; + var code = "time.ticks_diff(" + end + ", " + start + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const system_timer_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_NONE) || 'None'; + var period = generator.valueToCode(this, 'period', generator.ORDER_NONE) || '0'; + var mode = this.getFieldValue('mode'); + var callback = generator.valueToCode(this, 'callback', generator.ORDER_NONE) || 'None'; + var code = `${v}.init(period=${period}, mode=machine.Timer.${mode}, callback=${callback})\n`; + return code; +} + +export const system_timer_deinit = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_NONE) || 'None'; + var code = `${v}.deinit()\n`; + return code; +} + +export const system_wdt_init = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var period = generator.valueToCode(this, "period", generator.ORDER_NONE) || "0"; + var code = 'wdt = machine.WDT(timeout= ' + period + ')\n'; + return code; +} + +export const system_wdt_feed = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var code = 'wdt.feed()\n'; + return code; +} + +export const system_machine_reset = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var code = 'machine.reset()\n'; + return code; +} + +export const system_bitbot_shutdown = function (_, generator) { + generator.definitions_['import_bitbot_onboard_bot51'] = 'from bitbot import onboard_bot51'; + var code = 'onboard_bot51.shutdown()\n'; + return code; +} + +export const Timer_init = system_timer_init; +export const system_timer = system_timer_init; +export const timer2 = system_timer_init; +export const time_ticks_diff = system_ticks_diff; +export const base_delay = controls_delay; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/generators/weather.js b/mixly/boards/default_src/micropython/generators/weather.js new file mode 100644 index 00000000..890183ab --- /dev/null +++ b/mixly/boards/default_src/micropython/generators/weather.js @@ -0,0 +1,160 @@ +export const WEATHER_NOW = function (_, generator) { + generator.definitions_['import_seniverse_api'] = "import seniverse_api"; + var dropdown_mode = this.getFieldValue('mode'); + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var code = 'seniverse_api.' + dropdown_mode + '(' + key + ', ' + addr + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const WEATHER_DAILY = function (_, generator) { + generator.definitions_['import_seniverse_api'] = "import seniverse_api"; + var dropdown_mode = this.getFieldValue('mode'); + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var day = generator.valueToCode(this, 'day', generator.ORDER_ATOMIC); + var code = 'seniverse_api.' + dropdown_mode + '(' + key + ', ' + addr + ', ' + day + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const WEATHER_HOUR = function (_, generator) { + generator.definitions_['import_seniverse_api'] = "import seniverse_api"; + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var hour = generator.valueToCode(this, 'hour', generator.ORDER_ATOMIC); + var code = 'seniverse_api.weather_hourly(' + key + ', ' + addr + ', ' + hour + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const Weather_now = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var dropdown_mode = this.getFieldValue('mode'); + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var code = dropdown_mode + '.request(' + key + ', ' + addr + ')\n'; + return code; +}; + +export const Weather_now_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + if (content == 'none') { + var code = 'Weather_now.analysis()'; + } else { + var code = 'Weather_now.analysis("' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Air_now_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + if (content == 'none') { + var code = 'Air_now.analysis()'; + } else { + var code = 'Air_now.analysis("' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Weather_alarm_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + if (content == 'none') { + var code = 'Weather_alarm.analysis()'; + } else { + var code = 'Weather_alarm.analysis("' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Life_suggestion_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + if (content == 'none') { + var code = 'Life_suggestion.analysis()'; + } else { + var code = 'Life_suggestion.analysis("' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Tide_daily_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + if (content == 'none') { + var code = 'Tide_daily.analysis()'; + } else { + var code = 'Tide_daily.analysis("' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Location_search_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + if (content == 'none') { + var code = 'Location_search.analysis()'; + } else { + var code = 'Location_search.analysis("' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Weather_daily = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var dropdown_mode = this.getFieldValue('mode'); + var key = generator.valueToCode(this, 'key', generator.ORDER_ATOMIC); + var addr = generator.valueToCode(this, 'addr', generator.ORDER_ATOMIC); + var day = generator.valueToCode(this, 'day', generator.ORDER_ATOMIC); + var code = dropdown_mode + '.request(' + key + ', ' + addr + ', ' + day + ')\n'; + return code; +}; + +export const Weather_daily_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + var day = generator.valueToCode(this, 'day', generator.ORDER_ATOMIC); + if (content == 'none') { + var code = 'Weather_daily.analysis(' + day + ')'; + } else { + var code = 'Weather_daily.analysis(' + day + ', "' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Air_daily_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + var day = generator.valueToCode(this, 'day', generator.ORDER_ATOMIC); + if (content == 'none') { + var code = 'Air_daily.analysis(' + day + ')'; + } else { + var code = 'Air_daily.analysis(' + day + ', "' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Geo_sun_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + var day = generator.valueToCode(this, 'day', generator.ORDER_ATOMIC); + if (content == 'none') { + var code = 'Geo_sun.analysis(' + day + ')'; + } else { + var code = 'Geo_sun.analysis(' + day + ', "' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; + +export const Geo_moon_content = function (_, generator) { + generator.definitions_['import_seniverse_api*'] = "from seniverse_api import *"; + var content = this.getFieldValue('content'); + var day = generator.valueToCode(this, 'day', generator.ORDER_ATOMIC); + if (content == 'none') { + var code = 'Geo_moon.analysis(' + day + ')'; + } else { + var code = 'Geo_moon.analysis(' + day + ', "' + content + '")'; + } + return [code, generator.ORDER_ATOMIC]; +}; \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/index.js b/mixly/boards/default_src/micropython/index.js new file mode 100644 index 00000000..e69de29b diff --git a/mixly/boards/default_src/micropython/language/en.js b/mixly/boards/default_src/micropython/language/en.js new file mode 100644 index 00000000..031db7f0 --- /dev/null +++ b/mixly/boards/default_src/micropython/language/en.js @@ -0,0 +1,9 @@ +import * as Mixly from 'mixly'; +import TEMPLATE from '../template/board-config-message.html'; + +const { XML } = Mixly; + +export const MICROPYTHON_CONFIG_MESSAGE_BURN_SPEED = XML.render(TEMPLATE, { + title: 'Burn Speed', + message: 'To select the flashing speed, change the Burn Speed. This value will be used for flashing the code to the device. If you have issues while flashing the device at high speed, try to decrease this value. This could be due to the external serial-to-USB chip limitations.' +}); \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/language/zh-hans.js b/mixly/boards/default_src/micropython/language/zh-hans.js new file mode 100644 index 00000000..f89ce7b8 --- /dev/null +++ b/mixly/boards/default_src/micropython/language/zh-hans.js @@ -0,0 +1,9 @@ +import * as Mixly from 'mixly'; +import TEMPLATE from '../template/board-config-message.html'; + +const { XML } = Mixly; + +export const MICROPYTHON_CONFIG_MESSAGE_BURN_SPEED = XML.render(TEMPLATE, { + title: '烧录速度', + message: '要选择烧录速度,请更改“Burn Speed”,此值将用于向设备烧录代码。如果在用较高的烧录速度时出现问题,请尝试减小此值,这可能是由于外部串行到USB芯片的限制。' +}); \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/language/zh-hant.js b/mixly/boards/default_src/micropython/language/zh-hant.js new file mode 100644 index 00000000..2ed6d2f0 --- /dev/null +++ b/mixly/boards/default_src/micropython/language/zh-hant.js @@ -0,0 +1,9 @@ +import * as Mixly from 'mixly'; +import TEMPLATE from '../template/board-config-message.html'; + +const { XML } = Mixly; + +export const MICROPYTHON_CONFIG_MESSAGE_BURN_SPEED = XML.render(TEMPLATE, { + title: '燒錄速度', + message: '要選擇燒錄速度,請更改“Burn Speed”,此值將用於向設備燒錄程式碼。如果在用較高的燒錄速度時出現問題,請嘗試减小此值,這可能是由於外部串列到USB晶片的限制。' +}); \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/HZK12.bin b/mixly/boards/default_src/micropython/origin/build/HZK12.bin new file mode 100644 index 00000000..215c1825 Binary files /dev/null and b/mixly/boards/default_src/micropython/origin/build/HZK12.bin differ diff --git a/mixly/boards/default_src/micropython/origin/build/HZK16.bin b/mixly/boards/default_src/micropython/origin/build/HZK16.bin new file mode 100644 index 00000000..fd7b4c72 Binary files /dev/null and b/mixly/boards/default_src/micropython/origin/build/HZK16.bin differ diff --git a/mixly/boards/default_src/micropython/origin/build/HZK16_GBK.bin b/mixly/boards/default_src/micropython/origin/build/HZK16_GBK.bin new file mode 100644 index 00000000..2965cdb8 Binary files /dev/null and b/mixly/boards/default_src/micropython/origin/build/HZK16_GBK.bin differ diff --git a/mixly/boards/default_src/micropython/origin/build/esp_tts_voice_data_xiaole.dat b/mixly/boards/default_src/micropython/origin/build/esp_tts_voice_data_xiaole.dat new file mode 100644 index 00000000..a406c868 Binary files /dev/null and b/mixly/boards/default_src/micropython/origin/build/esp_tts_voice_data_xiaole.dat differ diff --git a/mixly/boards/default_src/micropython/origin/build/esp_tts_voice_data_xiaoxin.dat b/mixly/boards/default_src/micropython/origin/build/esp_tts_voice_data_xiaoxin.dat new file mode 100644 index 00000000..ed150c2b Binary files /dev/null and b/mixly/boards/default_src/micropython/origin/build/esp_tts_voice_data_xiaoxin.dat differ diff --git a/mixly/boards/default_src/micropython/origin/build/lib/adafruit_miniqr.py b/mixly/boards/default_src/micropython/origin/build/lib/adafruit_miniqr.py new file mode 100644 index 00000000..f8fcb04c --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/adafruit_miniqr.py @@ -0,0 +1,602 @@ +# SPDX-FileCopyrightText: 2009 Kazuhiko Arase +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Ported from the Javascript library by Sam Curren +# QRCode for Javascript +# http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/qrcode.js +# +# Minimized for CircuitPython by ladyada for adafruit industries +# +# The word "QR Code" is registered trademark of +# DENSO WAVE INCORPORATED +# http://www.denso-wave.com/qrcode/faqpatent-e.html +""" +`adafruit_miniqr` +==================================================== + +A non-hardware dependant miniature QR generator library. All native Python! + +* Author(s): ladyada + +Implementation Notes +-------------------- + +**Hardware:** + +* Any! + +**Software and Dependencies:** + +* Python 3 + +""" + +# imports +import math + +try: + from typing import Dict, List, Optional, Tuple +except ImportError: + pass + +__version__ = "0.0.0+auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_miniQR.git" + +# Consts! +M = 0 +L = 1 +H = 2 +Q = 3 + +_MODE_8BIT_BYTE = 1 << 2 +_PAD0 = 0xEC +_PAD1 = 0x11 + +# Optimized polynomial helpers + + +def _glog(n: int) -> int: + """Lookup log(n) from pre-calculated byte table""" + if n < 1: + raise ValueError("glog(" + n + ")") + return LOG_TABLE[n] + + +def _gexp(n: int) -> int: + """Lookup exp(n) from pre-calculated byte table""" + while n < 0: + n += 255 + while n >= 256: + n -= 255 + return EXP_TABLE[n] + + +EXP_TABLE = b"\x01\x02\x04\x08\x10 @\x80\x1d:t\xe8\xcd\x87\x13&L\x98-Z\xb4u\xea\xc9\x8f\x03\x06\x0c\x180`\xc0\x9d'N\x9c%J\x945j\xd4\xb5w\xee\xc1\x9f#F\x8c\x05\n\x14(P\xa0]\xbai\xd2\xb9o\xde\xa1_\xbea\xc2\x99/^\xbce\xca\x89\x0f\x1e|\xf8\xed\xc7\x93;v\xec\xc5\x973f\xcc\x85\x17.\\\xb8m\xda\xa9O\x9e!B\x84\x15*T\xa8M\x9a)R\xa4U\xaaI\x929r\xe4\xd5\xb7s\xe6\xd1\xbfc\xc6\x91?~\xfc\xe5\xd7\xb3{\xf6\xf1\xff\xe3\xdb\xabK\x961b\xc4\x957n\xdc\xa5W\xaeA\x82\x192d\xc8\x8d\x07\x0e\x1c8p\xe0\xdd\xa7S\xa6Q\xa2Y\xb2y\xf2\xf9\xef\xc3\x9b+V\xacE\x8a\t\x12$H\x90=z\xf4\xf5\xf7\xf3\xfb\xeb\xcb\x8b\x0b\x16,X\xb0}\xfa\xe9\xcf\x83\x1b6l\xd8\xadG\x8e\x01" # noqa: E501 + +LOG_TABLE = b"\x00\x00\x01\x19\x022\x1a\xc6\x03\xdf3\xee\x1bh\xc7K\x04d\xe0\x0e4\x8d\xef\x81\x1c\xc1i\xf8\xc8\x08Lq\x05\x8ae/\xe1$\x0f!5\x93\x8e\xda\xf0\x12\x82E\x1d\xb5\xc2}j'\xf9\xb9\xc9\x9a\txM\xe4r\xa6\x06\xbf\x8bbf\xdd0\xfd\xe2\x98%\xb3\x10\x91\"\x886\xd0\x94\xce\x8f\x96\xdb\xbd\xf1\xd2\x13\\\x838F@\x1eB\xb6\xa3\xc3H~nk:(T\xfa\x85\xba=\xca^\x9b\x9f\n\x15y+N\xd4\xe5\xacs\xf3\xa7W\x07p\xc0\xf7\x8c\x80c\rgJ\xde\xed1\xc5\xfe\x18\xe3\xa5\x99w&\xb8\xb4|\x11D\x92\xd9# \x89.7?\xd1[\x95\xbc\xcf\xcd\x90\x87\x97\xb2\xdc\xfc\xbea\xf2V\xd3\xab\x14*]\x9e\x84<9SGmA\xa2\x1f-C\xd8\xb7{\xa4v\xc4\x17I\xec\x7f\x0co\xf6l\xa1;R)\x9dU\xaa\xfb`\x86\xb1\xbb\xcc>Z\xcbY_\xb0\x9c\xa9\xa0Q\x0b\xf5\x16\xebzu,\xd7O\xae\xd5\xe9\xe6\xe7\xad\xe8t\xd6\xf4\xea\xa8PX\xaf" # noqa: E501 + + +class QRCode: + """The generator class for QR code matrices""" + + def __init__(self, *, qr_type: Optional[int] = None, error_correct: int = L): + """Initialize an empty QR code. You can define the `qr_type` (size) + of the code matrix, or have the libary auto-select the smallest + match. Default `error_correct` is type L (7%), but you can select M, + Q or H.""" + self.type = qr_type + self.ECC = error_correct + self.matrix = None + self.module_count = 0 + self.data_cache = None + self.data_list = [] + + def add_data(self, data: bytes) -> None: + """Add more data to the QR code, must be bytestring stype""" + self.data_list.append(data) + datalen = sum(len(x) for x in self.data_list) + if not self.type: + for qr_type in range(1, 10): + rs_blocks = _get_rs_blocks(qr_type, self.ECC) + total_data_count = 0 + for block in rs_blocks: + total_data_count += block["data"] + if total_data_count > datalen: + self.type = qr_type + break + self.data_cache = None + + def make(self, *, test: bool = False, mask_pattern: int = 0) -> None: + """Perform the actual generation of the QR matrix. To keep things + small and speedy we don't generate all 8 mask patterns and pick + the best. Instead, please pass in a desired mask_pattern, the + default mask is 0.""" + self.module_count = self.type * 4 + 17 + self.matrix = QRBitMatrix(self.module_count, self.module_count) + + self._setup_position_probe_pattern(0, 0) + self._setup_position_probe_pattern(self.module_count - 7, 0) + self._setup_position_probe_pattern(0, self.module_count - 7) + self._setup_position_adjust_pattern() + self._setup_timing_pattern() + self._setup_type_info(test, mask_pattern) + + if self.type >= 7: + self._setup_type_number(test) + + if self.data_cache is None: + self.data_cache = QRCode._create_data(self.type, self.ECC, self.data_list) + self._map_data(self.data_cache, mask_pattern) + + def _setup_position_probe_pattern(self, row: int, col: int) -> None: + """Add the positition probe data pixels to the matrix""" + for r in range(-1, 8): + if row + r <= -1 or self.module_count <= row + r: + continue + for c in range(-1, 8): + if col + c <= -1 or self.module_count <= col + c: + continue + test = ( + (0 <= r <= 6 and (c in (0, 6))) + or (0 <= c <= 6 and (r in (0, 6))) + or (2 <= r <= 4 and 2 <= c <= 4) + ) + self.matrix[row + r, col + c] = test + + def _setup_timing_pattern(self) -> None: + """Add the timing data pixels to the matrix""" + for r in range(8, self.module_count - 8): + if self.matrix[r, 6] is not None: + continue + self.matrix[r, 6] = r % 2 == 0 + + for c in range(8, self.module_count - 8): + if self.matrix[6, c] is not None: + continue + self.matrix[6, c] = c % 2 == 0 + + def _setup_position_adjust_pattern(self) -> None: + """Add the position adjust data pixels to the matrix""" + pos = QRUtil.get_pattern_position(self.type) + + for row in pos: + for col in pos: + if self.matrix[row, col] is not None: + continue + + for r in range(-2, 3): + for c in range(-2, 3): + test = abs(r) == 2 or abs(c) == 2 or (r == 0 and c == 0) + self.matrix[row + r, col + c] = test + + def _setup_type_number(self, test: bool) -> None: + """Add the type number pixels to the matrix""" + bits = QRUtil.get_BCH_type_number(self.type) + + for i in range(18): + mod = not test and ((bits >> i) & 1) == 1 + self.matrix[i // 3, i % 3 + self.module_count - 8 - 3] = mod + + for i in range(18): + mod = not test and ((bits >> i) & 1) == 1 + self.matrix[i % 3 + self.module_count - 8 - 3, i // 3] = mod + + def _setup_type_info(self, test: bool, mask_pattern: int) -> None: + """Add the type info pixels to the matrix""" + data = (self.ECC << 3) | mask_pattern + bits = QRUtil.get_BCH_type_info(data) + + # // vertical + for i in range(15): + mod = not test and ((bits >> i) & 1) == 1 + if i < 6: + self.matrix[i, 8] = mod + elif i < 8: + self.matrix[i + 1, 8] = mod + else: + self.matrix[self.module_count - 15 + i, 8] = mod + + # // horizontal + for i in range(15): + mod = not test and ((bits >> i) & 1) == 1 + if i < 8: + self.matrix[8, self.module_count - i - 1] = mod + elif i < 9: + self.matrix[8, 15 - i - 1 + 1] = mod + else: + self.matrix[8, 15 - i - 1] = mod + + # // fixed module + self.matrix[self.module_count - 8, 8] = not test + + def _map_data(self, data: bytes, mask_pattern: int) -> None: + """Map the data onto the QR code""" + inc = -1 + row = self.module_count - 1 + bit_idx = 7 + byte_idx = 0 + + for col in range(self.module_count - 1, 0, -2): + if col == 6: + col -= 1 # noqa: PLW2901 loop variable overwritten + + while True: + for c in range(2): + if self.matrix[row, col - c] is None: + dark = False + if byte_idx < len(data): + dark = ((data[byte_idx] >> bit_idx) & 1) == 1 + mask = QRUtil.get_mask(mask_pattern, row, col - c) + if mask: + dark = not dark + self.matrix[row, col - c] = dark + bit_idx -= 1 + if bit_idx == -1: + byte_idx += 1 + bit_idx = 7 + row += inc + if row < 0 or self.module_count <= row: + row -= inc + inc = -inc + break + + @staticmethod + def _create_data(qr_type: int, ecc: int, data_list: list) -> bytes: + """Check and format data into bit buffer""" + rs_blocks = _get_rs_blocks(qr_type, ecc) + + buffer = QRBitBuffer() + + for data in data_list: + if isinstance(data, str): + data = str.encode(data) # noqa: PLW2901 loop variable overwritten + buffer.put(_MODE_8BIT_BYTE, 4) + buffer.put(len(data), 8) + for byte in data: + buffer.put(byte, 8) + + # // calc num max data. + total_data_count = 0 + for block in rs_blocks: + total_data_count += block["data"] + + if buffer.get_length_bits() > total_data_count * 8: + raise RuntimeError( + "Code length overflow: %d > %d" % (buffer.get_length_bits(), total_data_count * 8) + ) + + # // end code + if buffer.get_length_bits() + 4 <= total_data_count * 8: + buffer.put(0, 4) + + # // padding + while buffer.get_length_bits() % 8 != 0: + buffer.put_bit(False) + + # // padding + while True: + if buffer.get_length_bits() >= total_data_count * 8: + break + buffer.put(_PAD0, 8) + if buffer.get_length_bits() >= total_data_count * 8: + break + buffer.put(_PAD1, 8) + + return QRCode._create_bytes(buffer, rs_blocks) + + @staticmethod + def _create_bytes(buffer: bytes, rs_blocks: List[Dict]) -> bytes: # noqa: PLR0912 Too many branches + """Perform error calculation math on bit buffer""" + + offset = 0 + max_dc_count = 0 + max_ec_count = 0 + + dcdata = [0] * len(rs_blocks) + ecdata = [0] * len(rs_blocks) + + for r, block in enumerate(rs_blocks): + dc_count = block["data"] + ec_count = block["total"] - dc_count + + max_dc_count = max(max_dc_count, dc_count) + max_ec_count = max(max_ec_count, ec_count) + + dcdata[r] = [0] * dc_count + + for i in range(len(dcdata[r])): + dcdata[r][i] = 0xFF & buffer.buffer[i + offset] + offset += dc_count + + rs_poly = QRUtil.get_error_correct_polynomial(ec_count) + mod_poly = QRPolynomial(dcdata[r], rs_poly.get_length() - 1) + + while True: + if mod_poly.get_length() - rs_poly.get_length() < 0: + break + ratio = _glog(mod_poly.get(0)) - _glog(rs_poly.get(0)) + num = [0 for x in range(mod_poly.get_length())] + for i in range(mod_poly.get_length()): + num[i] = mod_poly.get(i) + for i in range(rs_poly.get_length()): + num[i] ^= _gexp(_glog(rs_poly.get(i)) + ratio) + mod_poly = QRPolynomial(num, 0) + + ecdata[r] = [0 for x in range(rs_poly.get_length() - 1)] + for i in range(len(ecdata[r])): + mod_index = i + mod_poly.get_length() - len(ecdata[r]) + if mod_index >= 0: + ecdata[r][i] = mod_poly.get(mod_index) + else: + ecdata[r][i] = 0 + + total_code_count = 0 + for block in rs_blocks: + total_code_count += block["total"] + + data = [None] * total_code_count + index = 0 + + for i in range(max_dc_count): + for r in range(len(rs_blocks)): + if i < len(dcdata[r]): + data[index] = dcdata[r][i] + index += 1 + + for i in range(max_ec_count): + for r in range(len(rs_blocks)): + if i < len(ecdata[r]): + data[index] = ecdata[r][i] + index += 1 + + return data + + +class QRUtil: + """A selection of bit manipulation tools for QR generation and BCH encoding""" + + PATTERN_POSITION_TABLE = [ + b"", + b"\x06\x12", + b"\x06\x16", + b"\x06\x1a", + b"\x06\x1e", + b'\x06"', + b"\x06\x16&", + b"\x06\x18*", + b"\x06\x1a.", + b"\x06\x1c2", + ] + + G15 = 0b10100110111 + G18 = 0b1111100100101 + G15_MASK = 0b101010000010010 + + @staticmethod + def get_BCH_type_info(data: int) -> int: + """Encode with G15 BCH mask""" + d = data << 10 + while QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G15) >= 0: + d ^= QRUtil.G15 << (QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G15)) + + return ((data << 10) | d) ^ QRUtil.G15_MASK + + @staticmethod + def get_BCH_type_number(data: int) -> int: + """Encode with G18 BCH mask""" + d = data << 12 + while QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G18) >= 0: + d ^= QRUtil.G18 << (QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G18)) + return (data << 12) | d + + @staticmethod + def get_BCH_digit(data: int) -> int: + """Count digits in data""" + digit = 0 + while data != 0: + digit += 1 + data >>= 1 + return digit + + @staticmethod + def get_pattern_position(qr_type: int) -> bytes: + """The mask pattern position array for this QR type""" + return QRUtil.PATTERN_POSITION_TABLE[qr_type - 1] + + @staticmethod + def get_mask(mask: int, i: int, j: int) -> int: # noqa: PLR0911 Too many return statements + """Perform matching calculation on two vals for given pattern mask""" + if mask == 0: + return (i + j) % 2 == 0 + if mask == 1: + return i % 2 == 0 + if mask == 2: + return j % 3 == 0 + if mask == 3: + return (i + j) % 3 == 0 + if mask == 4: + return (math.floor(i / 2) + math.floor(j / 3)) % 2 == 0 + if mask == 5: + return (i * j) % 2 + (i * j) % 3 == 0 + if mask == 6: + return ((i * j) % 2 + (i * j) % 3) % 2 == 0 + if mask == 7: + return ((i * j) % 3 + (i + j) % 2) % 2 == 0 + raise ValueError("Bad mask pattern:" + mask) + + @staticmethod + def get_error_correct_polynomial(ecc_length: int) -> "QRPolynomial": + """Generate a ecc polynomial""" + poly = QRPolynomial([1], 0) + for i in range(ecc_length): + poly = poly.multiply(QRPolynomial([1, _gexp(i)], 0)) + return poly + + +class QRPolynomial: + """Structure for creating and manipulating error code polynomials""" + + def __init__(self, num: int, shift: int): + """Create a QR polynomial""" + if not num: + raise ValueError(num.length + "/" + shift) + offset = 0 + while offset < len(num) and num[offset] == 0: + offset += 1 + self.num = [0 for x in range(len(num) - offset + shift)] + for i in range(len(num) - offset): + self.num[i] = num[i + offset] + + def get(self, index: int) -> int: + """The exponent at the index location""" + return self.num[index] + + def get_length(self) -> int: + """Length of the poly""" + return len(self.num) + + def multiply(self, other_polynomial: "QRPolynomial") -> "QRPolynomial": + """Multiply two polynomials, returns a new one""" + num = [0 for x in range(self.get_length() + other_polynomial.get_length() - 1)] + + for i in range(self.get_length()): + for j in range(other_polynomial.get_length()): + num[i + j] ^= _gexp(_glog(self.get(i)) + _glog(other_polynomial.get(j))) + + return QRPolynomial(num, 0) + + +_QRRS_BLOCK_TABLE = ( + b"\x01\x1a\x10", + b"\x01\x1a\x13", + b"\x01\x1a\t", + b"\x01\x1a\r", + b"\x01,\x1c", + b'\x01,"', + b"\x01,\x10", + b"\x01,\x16", + b"\x01F,", + b"\x01F7", + b"\x02#\r", + b"\x02#\x11", + b"\x022 ", + b"\x01dP", + b"\x04\x19\t", + b"\x022\x18", + b"\x02C+", + b"\x01\x86l", + b'\x02!\x0b\x02"\x0c', + b'\x02!\x0f\x02"\x10', + b"\x04+\x1b", + b"\x02VD", + b"\x04+\x0f", + b"\x04+\x13", + b"\x041\x1f", + b"\x02bN", + b"\x04'\r\x01(\x0e", + b"\x02 \x0e\x04!\x0f", + b"\x02<&\x02='", + b"\x02ya", + b"\x04(\x0e\x02)\x0f", + b"\x04(\x12\x02)\x13", + b"\x03:$\x02;%", + b"\x02\x92t", + b"\x04$\x0c\x04%\r", + b"\x04$\x10\x04%\x11", +) + + +def _get_rs_blocks(qr_type: int, ecc: int) -> List[Dict]: + rs_block = _QRRS_BLOCK_TABLE[(qr_type - 1) * 4 + ecc] + + length = len(rs_block) // 3 + blocks = [] + for i in range(length): + count = rs_block[i * 3 + 0] + total = rs_block[i * 3 + 1] + data = rs_block[i * 3 + 2] + block = {"total": total, "data": data} + for _ in range(count): + blocks.append(block) + return blocks + + +class QRBitMatrix: + """A bit-packed storage class for matrices""" + + def __init__(self, width: int, height: int): + self.width = width + self.height = height + if width > 60: + raise ValueError("Max 60 bits wide:", width) + self.buffer = [0] * self.height * 2 + self.used = [0] * self.height * 2 + + def __repr__(self) -> str: + b = "" + for y in range(self.height): + for x in range(self.width): + if self[x, y]: + b += "X" + else: + b += "." + b += "\n" + return b + + def __getitem__(self, key: Tuple[int, int]) -> int: + x, y = key + if y > self.width: + raise ValueError() + i = 2 * x + (y // 30) + j = y % 30 + if not self.used[i] & (1 << j): + return None + return self.buffer[i] & (1 << j) + + def __setitem__(self, key: Tuple[int, int], value: int) -> None: + x, y = key + if y > self.width: + raise ValueError() + i = 2 * x + (y // 30) + j = y % 30 + if value: + self.buffer[i] |= 1 << j + else: + self.buffer[i] &= ~(1 << j) + self.used[i] |= 1 << j # buffer item was set + + +class QRBitBuffer: + """Storage class for a length of individual bits""" + + def __init__(self): + self.buffer = [] + self.length = 0 + + def __repr__(self) -> str: + return ".".join([str(n) for n in self.buffer]) + + def get(self, index: int) -> int: + """The bit value at a location""" + i = index // 8 + return self.buffer[i] & (1 << (7 - index % 8)) + + def put(self, num: int, length: int) -> None: + """Add a number of bits from a single integer value""" + for i in range(length): + self.put_bit(num & (1 << (length - i - 1))) + + def get_length_bits(self) -> int: + """Size of bit buffer""" + return self.length + + def put_bit(self, bit: int) -> None: + """Insert one bit at the end of the bit buffer""" + i = self.length // 8 + if len(self.buffer) <= i: + self.buffer.append(0) + if bit: + self.buffer[i] |= 0x80 >> (self.length % 8) + self.length += 1 diff --git a/mixly/boards/default_src/micropython/origin/build/lib/adxl345.py b/mixly/boards/default_src/micropython/origin/build/lib/adxl345.py new file mode 100644 index 00000000..32952553 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/adxl345.py @@ -0,0 +1,52 @@ +#ADXL345 +import time +import ustruct +from micropython import const + +DATA_FORMAT = const(0x31) +BW_RATE = const(0x2c) +POWER_CTL = const(0x2d) +INT_ENABLE = const(0x2E) +OFSX = const(0x1e) +OFSY = const(0x1f) +OFSZ = const(0x20) + +class ADXL345: + def __init__(self, i2c, address=0X53): + self._device = i2c + self._address = address + if self._rreg(0x0) != 0xe5: + raise AttributeError("Cannot find a ADXL345") + + self._wreg(DATA_FORMAT,0x2B) #16g量程 + self._wreg(BW_RATE,0x0A) #数据输出速度为100Hz + self._wreg(INT_ENABLE,0x00) #不使用中断 + + self._wreg(OFSX,0x00) + self._wreg(OFSY,0x00) + self._wreg(OFSZ,0x00) + self._wreg(POWER_CTL,0x08) #链接使能,测量模式 + time.sleep(0.5) + + def readXYZ(self): + x, = ustruct.unpack('= self._delay: + self._star = time.ticks_ms() + _buf = self._rreg(_AGS10_ADC) + self._voc = int.from_bytes(_buf[1:4], 'big') + self.ready = not (_buf[0] & 0x01) + return self._voc / 1000 + + def read(self, hcho_mw=30.033 , co2_mv=0.853, co2_base=400): + '''unit ppm''' + self.getdata + _voc = self._voc / 1000 #ppm + return round( _voc, 2), round( _voc / hcho_mw, 2), co2_base + round( _voc / co2_mv, 2) + + def tvoc(self): + return self.read()[0] + + def hcho(self, tvoc_mw=30.053): + return self.read(hcho_mw=hcho_mw)[1] + + def eco2(self, co2_mv=0.853): + return self.read(co2_mv=co2_mv)[2] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ahtx0.py b/mixly/boards/default_src/micropython/origin/build/lib/ahtx0.py new file mode 100644 index 00000000..d7887283 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ahtx0.py @@ -0,0 +1,88 @@ +""" +AHT21 + +Micropython library for the AHT21(temperature,humidity) +======================================================= + +#Changed from circuitpython to micropython 20220211 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" +import utime +from micropython import const + +AHTX0_I2CADDR_DEFAULT = const(0x38) # Default I2C address +AHTX0_CMD_INITIALIZE = const(0xE1) # Initialization command +AHTX0_CMD_TRIGGER = const(0xAC) # Trigger reading command +AHTX0_CMD_SOFTRESET = const(0xBA) # Soft reset command +AHTX0_STATUS_BUSY = const(0x80) # Status bit for busy +AHTX0_STATUS_CALIBRATED = const(0x08) # Status bit for calibrated + +class AHTx0: + """Interface library for AHT10/AHT20 temperature+humidity sensors""" + def __init__(self, i2c, address=AHTX0_I2CADDR_DEFAULT): + utime.sleep_ms(20) # 20ms delay to wake up + self._i2c = i2c + self._address = address + self._buf = bytearray(6) + self.reset() + if not self.initialize(): + raise AttributeError("Cannot find a AHTx0") + self._temp = None + self._humidity = None + + def reset(self): + """Perform a soft-reset of the AHT""" + self._buf[0] = AHTX0_CMD_SOFTRESET + self._i2c.writeto(self._address, self._buf[0:1]) + utime.sleep_ms(20) # 20ms delay to wake up + + def initialize(self): + """Ask the sensor to self-initialize. Returns True on success, False otherwise""" + self._buf[0] = AHTX0_CMD_INITIALIZE + self._buf[1] = 0x08 + self._buf[2] = 0x00 + self._i2c.writeto(self._address, self._buf[0:3]) + self._wait_for_idle() + if not self.status() & AHTX0_STATUS_CALIBRATED: + return False + return True + + def status(self): + """The status byte initially returned from the sensor, see datasheet for details""" + self._read_to_buffer() + return self._buf[0] + + def _read_to_buffer(self): + self._i2c.readfrom_into(self._address, self._buf) + + def _trigger_measurement(self): + """Internal function for triggering the AHT to read temp/humidity""" + self._buf[0] = AHTX0_CMD_TRIGGER + self._buf[1] = 0x33 + self._buf[2] = 0x00 + self._i2c.writeto(self._address, self._buf[0:3]) + + def _wait_for_idle(self): + while self.status() & AHTX0_STATUS_BUSY: + utime.sleep_ms(5) + + def _perform_measurement(self): + self._trigger_measurement() + self._wait_for_idle() + self._read_to_buffer() + + def humidity(self): + """The measured relative humidity in percent.""" + self._perform_measurement() + self._humidity = (self._buf[1] << 12) | (self._buf[2] << 4) | (self._buf[3] >> 4) + self._humidity = (self._humidity * 100) / 0x100000 + return self._humidity + + def temperature(self): + """The measured temperature in degrees Celcius.""" + self._perform_measurement() + self._temp = ((self._buf[3] & 0xF) << 16) | (self._buf[4] << 8) | self._buf[5] + self._temp = ((self._temp * 200.0) / 0x100000) - 50 + return self._temp \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ap3216c.py b/mixly/boards/default_src/micropython/origin/build/lib/ap3216c.py new file mode 100644 index 00000000..111b9c33 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ap3216c.py @@ -0,0 +1,59 @@ +""" +AP3216C + +MicroPython library for the AP3216C(ALS,PS,IRS) +======================================================= +#Preliminary composition 20240630 + +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +AP3216_ADD = const(0x1E) +AP_SYS_CMD = const(0x00) +AP_DAT = const(0x0A) +AP_ALS_CMD = const(0x10) +AP_PS_CMD = const(0x20) +AP_PS_LED = const(0x21) +Resolution = 0.35 + +class AP3216C: + def __init__(self, i2c_bus, addr=AP3216_ADD): + self._device = i2c_bus + self._address = addr + self._wreg(AP_SYS_CMD, 0x04) # SW reset + time.sleep_ms(100) + self._wreg(AP_SYS_CMD, 0x03) # 011: ALS and PS+IR functions active + self._wreg(AP_ALS_CMD, 0x00) # Range 1: 0 ~ 20661 Lux. Resolution = 0.35 lux/count. + self._wreg(AP_PS_CMD, 0x09) # PS gain:10 + self._wreg(AP_PS_LED, 0x23) # PS LED pulse:10 + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + @property + def getdata(self): + '''处理获取数据''' + #buf = self._rreg(AP_DAT, 6) + ir = (self._rreg(AP_DAT + 0) & 0x03) | self._rreg(AP_DAT + 1) << 2 + als= (self._rreg(AP_DAT + 2) | self._rreg(AP_DAT + 3) << 8) * Resolution + ps = (self._rreg(AP_DAT + 4) & 0x0F) | (self._rreg(AP_DAT + 5) & 0x3F) << 4 + return round(als, 2), ir, ps + + def als_vis(self): + '''可见光Lux''' + return self.getdata[0] + + def als_ir(self): + '''红外Lux''' + return self.getdata[1] + + def ps_nl(self): + '''接近距离''' + return self.getdata[2] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/apds9960.py b/mixly/boards/default_src/micropython/origin/build/lib/apds9960.py new file mode 100644 index 00000000..af4c4400 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/apds9960.py @@ -0,0 +1,294 @@ +""" +APDS9960` + +MicroPython library for the APDS9960(Supports gesture, proximity, and color detection) +======================================================= + +#Preliminary composition 20220224 +#base on https://github.com/adafruit/Adafruit_CircuitPython_BusDevice 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +_DEVICE_ID = const(0xAB) +_APDS9960_ENABLE = const(0x80) +_APDS9960_ATIME = const(0x81) +_APDS9960_PILT = const(0x89) +_APDS9960_PIHT = const(0x8B) +_APDS9960_PERS = const(0x8C) +_APDS9960_CONTROL = const(0x8F) +_APDS9960_ID = const(0x92) +_APDS9960_STATUS = const(0x93) +_APDS9960_CDATAL = const(0x94) +_APDS9960_PDATA = const(0x9C) +_APDS9960_GPENTH = const(0xA0) +_APDS9960_GEXTH = const(0xA1) +_APDS9960_GCONF1 = const(0xA2) +_APDS9960_GCONF2 = const(0xA3) +_APDS9960_GPULSE = const(0xA6) +_APDS9960_GCONF4 = const(0xAB) +_APDS9960_GFLVL = const(0xAE) +_APDS9960_GSTATUS = const(0xAF) +_APDS9960_AICLEAR = const(0xE7) +_APDS9960_GFIFO_U = const(0xFC) +_BIT_MASK_ENABLE_EN = const(0x01) +_BIT_MASK_ENABLE_COLOR = const(0x02) +_BIT_MASK_ENABLE_PROX = const(0x04) +_BIT_MASK_ENABLE_PROX_INT = const(0x20) +_BIT_MASK_ENABLE_GESTURE = const(0x40) +_BIT_MASK_STATUS_AVALID = const(0x01) +_BIT_MASK_STATUS_GINT = const(0x04) +_BIT_MASK_GSTATUS_GFOV = const(0x02) +_BIT_MASK_GCONF4_GFIFO_CLR = const(0x04) +_BIT_POS_PERS_PPERS = const(4) +_BIT_MASK_PERS_PPERS = const(0xF0) +_BIT_POS_CONTROL_AGAIN = const(0) +_BIT_MASK_CONTROL_AGAIN = const(3) +_BIT_POS_CONTROL_PGAIN = const(2) +_BIT_MASK_CONTROL_PGAIN = const(0x0C) +_BIT_POS_GCONF2_GGAIN = const(5) +_BIT_MASK_GCONF2_GGAIN = const(0x60) + +class APDS9960: + def __init__(self, i2c, address=0x39): + self._device = i2c + self._address = address + self._select = [True,True,True] + + if self._rreg(_APDS9960_ID) != _DEVICE_ID: + raise AttributeError("Cannot find a APDS9960") + + self.enable(True) # Re-enable sensor and wait 10ms for the power on delay to finish + time.sleep(0.010) + self._wreg(_APDS9960_GPENTH, 0x05) # Enter gesture engine at >= 5 proximity counts + self._wreg(_APDS9960_GEXTH, 0x1E) # Exit gesture engine if all counts drop below 30 + self._wreg(_APDS9960_GCONF1, 0x82) # GEXPERS: 2 (4 cycles), GEXMSK: 0 (default) GFIFOTH: 2 (8 datasets) + self._wreg(_APDS9960_GCONF2, 0x41) # GGAIN: 2 (4x), GLDRIVE: 100 mA (default), GWTIME: 1 (2.8ms) + self._wreg(_APDS9960_GPULSE, 0x85) # GPULSE: 5 (6 pulses), GPLEN: 2 (16 us) + self.color_integration_time(256) # ATIME: 256 (712ms color integration time, max count of 65535) + + # method for reading and writing to I2C + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _writecmdonly(self, val): + """Writes a command and 0 bytes of data to the I2C device""" + self._device.writeto(self._address,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _get_bit(self, reg, mask): + """Gets a single bit value from the I2C device's register""" + return bool(self._rreg(reg) & mask) + + def _set_bit(self, reg, mask, value): + """Sets a single bit value in the I2C device's register""" + buf=self._rreg(reg) + buf= buf | mask if value else buf & ~mask + self._wreg(reg,buf) + + def _set_bits(self, reg, pos, mask, value): + """Sets a multi-bit value in the I2C device's register""" + buf=self._rreg(reg) + buf = (buf & ~mask) | (value << pos) + self._wreg(reg,buf) + + def _color_data16(self, reg): + """Sends a command and reads 2 bytes of data from the I2C device""" + buf = self._rreg(reg,2) + return buf[1] << 8 | buf[0] + + def enable(self, value): + """sensor is enabled""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_EN, value) + + def enable_proximity(self, value): + """sensor's proximity engine is enabled.""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_PROX, value) + + def proximity_gain(self, value): + """""Proximity sensor gain value""" + # proximity_gain" "Gain Multiplier" "Note" + # 0, "1x", "Power-on Default" + # 1, "2x", "" + # 2, "4x", "" + # 3, "8x", "" + self._set_bits(_APDS9960_CONTROL, _BIT_POS_CONTROL_PGAIN, _BIT_MASK_CONTROL_PGAIN, value) + + def enable_gesture(self, value): + """sensor's gesture engine is enabled""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_GESTURE, value) + + def gesture_gain(self, value): + """Gesture mode gain value""" + # "gesture_gain" "Gain Multiplier" "Note" + # 0, "1x", "Power-on Default" + # 1, "2x", "" + # 2, "4x", "Driver Default" + # 3, "8x", "" + self._set_bits(_APDS9960_GCONF2, _BIT_POS_GCONF2_GGAIN, _BIT_MASK_GCONF2_GGAIN, value) + + def enable_color(self, value): + """sensor's color/light engine is enabled""" + self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_COLOR, value) + + def color_gain(self, value): + """Color/light sensor gain value""" + # "color_gain" "Gain Multiplier" "Note" + # 0, "1x", "Power-on Default" + # 1, "4x", "Driver Default" + # 2, "16x", "" + # 3, "64x", "" + self._set_bits(_APDS9960_CONTROL, _BIT_POS_CONTROL_AGAIN, _BIT_MASK_CONTROL_AGAIN, value) + + def color_integration_time(self, value): + """Color/light sensor gain""" + # "color_integration_time" "Time" "Max Count" "Note" + # 1, "2.78 ms", 1025, "Power-on Default" + # 10, "27.8 ms", 10241, "" + # 37, "103 ms", 37889, "" + # 72, "200 ms", 65535, "" + # 256, "712 ms", 65535, "Driver Default" + self._wreg(_APDS9960_ATIME, 256 - value) + + ## PROXIMITY + def proximity(self,gain=2): + """Proximity sensor data""" + if self._select[0]: + self._select=[False,True,True] + self.enable_proximity(True) + self.enable_gesture(False) + self.enable_color(False) + self.proximity_gain(gain) + + return self._rreg(_APDS9960_PDATA) + + ## GESTURE + def gesture(self,gain=3): + """Gesture sensor data""" + # If FIFOs have overflowed we're already way too late, so clear those FIFOs and wait + if self._select[1]: + self._select=[True,False,True] + self.enable_proximity(True) + self.enable_gesture(True) + self.enable_color(False) + self.gesture_gain(gain) + + if self._get_bit(_APDS9960_GSTATUS, _BIT_MASK_GSTATUS_GFOV): + self._set_bit(_APDS9960_GCONF4, _BIT_MASK_GCONF4_GFIFO_CLR, True) + wait_cycles = 0 + while ( not self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_GINT) and wait_cycles <= 30 ): + time.sleep(0.003) + wait_cycles += 1 + + frame = [] + datasets_available = self._rreg(_APDS9960_GFLVL) + if (self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_GINT) and datasets_available > 0 ): + + buffer = bytearray(128) + buffer_dataset = bytearray(4) + while True: + dataset_count = self._rreg(_APDS9960_GFLVL) + if dataset_count == 0: + break + buffer=self._rreg(_APDS9960_GFIFO_U,min(128, 1 + (dataset_count * 4))) + # Unpack data stream into more usable U/D/L/R datasets for analysis + idx = 0 + for i in range(dataset_count): + idx = i * 4 + buffer_dataset[0] = buffer[idx] + buffer_dataset[1] = buffer[idx + 1] + buffer_dataset[2] = buffer[idx + 2] + buffer_dataset[3] = buffer[idx + 3] + + if ((not all(val == 255 for val in buffer_dataset)) + and (not all(val == 0 for val in buffer_dataset)) + and (all(val >= 30 for val in buffer_dataset)) + ): + if len(frame) < 2: + frame.append(tuple(buffer_dataset)) + else: + frame[1] = tuple(buffer_dataset) + time.sleep(0.03) + if len(frame) < 2: + return None + # Determine our up/down and left/right ratios along with our first/last deltas + f_r_ud = ((frame[0][0] - frame[0][1]) * 100) // (frame[0][0] + frame[0][1]) + f_r_lr = ((frame[0][2] - frame[0][3]) * 100) // (frame[0][2] + frame[0][3]) + l_r_ud = ((frame[1][0] - frame[1][1]) * 100) // (frame[1][0] + frame[1][1]) + l_r_lr = ((frame[1][2] - frame[1][3]) * 100) // (frame[1][2] + frame[1][3]) + delta_ud = l_r_ud - f_r_ud + delta_lr = l_r_lr - f_r_lr + # Make our first guess at what gesture we saw, if any + state_ud = 0 + state_lr = 0 + if delta_ud >= 30: + state_ud = 1 + elif delta_ud <= -30: + state_ud = -1 + + if delta_lr >= 30: + state_lr = 1 + elif delta_lr <= -30: + state_lr = -1 + # Make our final decision based on our first guess and, if required, the delta data + gesture_found = 0 + # Easy cases + if state_ud == -1 and state_lr == 0: + gesture_found = 1 + elif state_ud == 1 and state_lr == 0: + gesture_found = 2 + elif state_ud == 0 and state_lr == -1: + gesture_found = 3 + elif state_ud == 0 and state_lr == 1: + gesture_found = 4 + # Not so easy cases + if gesture_found == 0: + if state_ud == -1 and state_lr == 1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 1 + else: + gesture_found = 4 + elif state_ud == 1 and state_lr == -1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 2 + else: + gesture_found = 3 + elif state_ud == -1 and state_lr == -1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 1 + else: + gesture_found = 3 + elif state_ud == 1 and state_lr == 1: + if abs(delta_ud) > abs(delta_lr): + gesture_found = 2 + else: + gesture_found = 3 + + dir_lookup = [None,"left", "right", "down", "up"] + return dir_lookup[gesture_found] + + ## COLOR + def color(self,gain=1): + """Tuple containing red, green, blue, and clear light intensity values""" + if self._select[2]: + self._select=[True,True,False] + self.enable_proximity(False) + self.enable_gesture(False) + self.enable_color(True) + self.color_gain(gain) + + while not self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_AVALID): + time.sleep(0.005) #"""Color data ready flag""" + return ( + self._color_data16(_APDS9960_CDATAL + 2), + self._color_data16(_APDS9960_CDATAL + 4), + self._color_data16(_APDS9960_CDATAL + 6), + self._color_data16(_APDS9960_CDATAL), + ) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/baidu_speech.py b/mixly/boards/default_src/micropython/origin/build/lib/baidu_speech.py new file mode 100644 index 00000000..d45b2cc9 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/baidu_speech.py @@ -0,0 +1,114 @@ +""" +Baidu ASR API + +MicroPython library for Baidu ASR API +======================================================= + +#Preliminary composition 20230223 +#https://ai.baidu.com/ai-doc/SPEECH/Ek39uxgre +#https://ai.baidu.com/unit/home#/home + +@dahanzimin From the Mixly Team +""" + +import json,gc +import urequests,array +from ubinascii import hexlify +from machine import Timer,unique_id + +'''Set constant''' +_framerate=8000 +_unique_id=hexlify(unique_id()).decode() + +def urequests_api(method, url, **kw): + '''Request data''' + try: + return json.loads(urequests.request(method, url, **kw).text) + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected",e) + +def fetch_token(API_Key,Secret_Key): + """Get access_token""" + url='http://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={}&client_secret={}'.format(API_Key,Secret_Key) + results=urequests_api("GET",url) + if "error_description" in results.keys(): + raise ValueError(results["error_description"]) + if "access_token" in results.keys(): + return results["access_token"] + +class Recorder: + def __init__(self, adc,timer=2): + self._timer=Timer(timer) + self._mic=adc + + def _timer_callback(self,timer): + '''Timer callback read microphone''' + try: + _mic=self._mic.read_u16()-32768 + self._pcm_buffer.append(_mic &0xFF) + self._pcm_buffer.append(_mic >>8) + self._record_time-=1 + except: + print("Warning: MemoryError!") + self._pcm_buffer=bytearray() + gc.collect() + self._record_time=0 + + def record(self,record_time=1): + """Call timer to record audio""" + self._pcm_buffer=bytearray() + gc.collect() + self._record_time=record_time*_framerate + self._timer.init(freq =_framerate, mode = Timer.PERIODIC, callback = self._timer_callback) + while True: + if self._record_time <= 0: + self._timer.deinit() + gc.collect() + return self._pcm_buffer + +class ASR(Recorder): + def __init__(self, adc, API_Key, Secret_Key, timer=2): + self._token=fetch_token(API_Key,Secret_Key) + super().__init__(adc,timer) + + def recognize(self,record_time=1,dev_pid=1537): + """Access API to get voice results""" + pcm_buffer=self.record(record_time) + if max(pcm_buffer)>=250: + url='http://vop.baidu.com/server_api?dev_pid={}&cuid={}&token={}'.format(dev_pid,_unique_id,self._token) + headers = {'Content-Type': 'audio/pcm; rate={}'.format(_framerate)} + results=urequests_api("POST",url,data=pcm_buffer,headers=headers) + if results["err_no"] != 0: + raise ValueError(results["err_msg"],results["err_no"]) + elif results["err_msg"] == "success.": + gc.collect() + return results["result"][0] + else: + return '' + +class UNIT: + def __init__(self, API_Key, Secret_Key): + self._token=fetch_token(API_Key,Secret_Key) + self._session_id="" + + def chatbot(self,chatbot_id,query): + """Access API to intelligent dialog""" + if len(query) > 0: + url='https://aip.baidubce.com/rpc/2.0/unit/service/v3/chat?access_token={}'.format(self._token) + data={"log_id":"log"+_unique_id, + "version":"3.0", + "service_id":chatbot_id, + "session_id":self._session_id, + "request":{"query":query,"terminal_id":_unique_id}} + headers = {"content-type": "application/json"} + results=urequests_api("POST",url,data=json.dumps(data).encode(),headers=headers) + if results["error_code"] != 0: + raise ValueError(results["error_msg"],results["error_code"]) + elif results["error_msg"] == "success": + self._session_id=results["result"]['session_id'] + gc.collect() + return results["result"]['responses'][0]['actions'][0]['say'] + else: + return '' + +gc.collect() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/base64.py b/mixly/boards/default_src/micropython/origin/build/lib/base64.py new file mode 100644 index 00000000..d6baca05 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/base64.py @@ -0,0 +1,480 @@ +#! /usr/bin/env python3 + +"""RFC 3548: Base16, Base32, Base64 Data Encodings""" + +# Modified 04-Oct-1995 by Jack Jansen to use binascii module +# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support +# Modified 22-May-2007 by Guido van Rossum to use bytes everywhere + +import re +import struct +import binascii + + +__all__ = [ + # Legacy interface exports traditional RFC 1521 Base64 encodings + "encode", + "decode", + "encodebytes", + "decodebytes", + # Generalized interface for other encodings + "b64encode", + "b64decode", + "b32encode", + "b32decode", + "b16encode", + "b16decode", + # Standard Base64 encoding + "standard_b64encode", + "standard_b64decode", + # Some common Base64 alternatives. As referenced by RFC 3458, see thread + # starting at: + # + # http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html + "urlsafe_b64encode", + "urlsafe_b64decode", +] + + +bytes_types = (bytes, bytearray) # Types acceptable as binary data + + +def _bytes_from_decode_data(s): + if isinstance(s, str): + try: + return s.encode("ascii") + # except UnicodeEncodeError: + except: + raise ValueError("string argument should contain only ASCII characters") + elif isinstance(s, bytes_types): + return s + else: + raise TypeError("argument should be bytes or ASCII string, not %s" % s.__class__.__name__) + + +def _maketrans(f, t): + """Re-implement bytes.maketrans() as there is no such function in micropython""" + if len(f) != len(t): + raise ValueError("maketrans arguments must have same length") + translation_table = dict(zip(f, t)) + return translation_table + + +def _translate(input_bytes, trans_table): + """Re-implement bytes.translate() as there is no such function in micropython""" + result = bytearray() + + for byte in input_bytes: + translated_byte = trans_table.get(byte, byte) + result.append(translated_byte) + + return bytes(result) + + +# Base64 encoding/decoding uses binascii + + +def b64encode(s, altchars=None): + """Encode a byte string using Base64. + + s is the byte string to encode. Optional altchars must be a byte + string of length 2 which specifies an alternative alphabet for the + '+' and '/' characters. This allows an application to + e.g. generate url or filesystem safe Base64 strings. + + The encoded byte string is returned. + """ + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + # Strip off the trailing newline + encoded = binascii.b2a_base64(s)[:-1] + if altchars is not None: + if not isinstance(altchars, bytes_types): + raise TypeError("expected bytes, not %s" % altchars.__class__.__name__) + assert len(altchars) == 2, repr(altchars) + encoded = _translate(encoded, _maketrans(b"+/", altchars)) + return encoded + + +def b64decode(s, altchars=None, validate=False): + """Decode a Base64 encoded byte string. + + s is the byte string to decode. Optional altchars must be a + string of length 2 which specifies the alternative alphabet used + instead of the '+' and '/' characters. + + The decoded string is returned. A binascii.Error is raised if s is + incorrectly padded. + + If validate is False (the default), non-base64-alphabet characters are + discarded prior to the padding check. If validate is True, + non-base64-alphabet characters in the input result in a binascii.Error. + """ + s = _bytes_from_decode_data(s) + if altchars is not None: + altchars = _bytes_from_decode_data(altchars) + assert len(altchars) == 2, repr(altchars) + s = _translate(s, _maketrans(altchars, b"+/")) + if validate and not re.match(b"^[A-Za-z0-9+/]*=*$", s): + raise binascii.Error("Non-base64 digit found") + return binascii.a2b_base64(s) + + +def standard_b64encode(s): + """Encode a byte string using the standard Base64 alphabet. + + s is the byte string to encode. The encoded byte string is returned. + """ + return b64encode(s) + + +def standard_b64decode(s): + """Decode a byte string encoded with the standard Base64 alphabet. + + s is the byte string to decode. The decoded byte string is + returned. binascii.Error is raised if the input is incorrectly + padded or if there are non-alphabet characters present in the + input. + """ + return b64decode(s) + + +# _urlsafe_encode_translation = _maketrans(b'+/', b'-_') +# _urlsafe_decode_translation = _maketrans(b'-_', b'+/') + + +def urlsafe_b64encode(s): + """Encode a byte string using a url-safe Base64 alphabet. + + s is the byte string to encode. The encoded byte string is + returned. The alphabet uses '-' instead of '+' and '_' instead of + '/'. + """ + # return b64encode(s).translate(_urlsafe_encode_translation) + return b64encode(s, b"-_").rstrip(b"\n") + + +def urlsafe_b64decode(s): + """Decode a byte string encoded with the standard Base64 alphabet. + + s is the byte string to decode. The decoded byte string is + returned. binascii.Error is raised if the input is incorrectly + padded or if there are non-alphabet characters present in the + input. + + The alphabet uses '-' instead of '+' and '_' instead of '/'. + """ + # s = _bytes_from_decode_data(s) + # s = s.translate(_urlsafe_decode_translation) + # return b64decode(s) + raise NotImplementedError() + + +# Base32 encoding/decoding must be done in Python +_b32alphabet = { + 0: b"A", + 9: b"J", + 18: b"S", + 27: b"3", + 1: b"B", + 10: b"K", + 19: b"T", + 28: b"4", + 2: b"C", + 11: b"L", + 20: b"U", + 29: b"5", + 3: b"D", + 12: b"M", + 21: b"V", + 30: b"6", + 4: b"E", + 13: b"N", + 22: b"W", + 31: b"7", + 5: b"F", + 14: b"O", + 23: b"X", + 6: b"G", + 15: b"P", + 24: b"Y", + 7: b"H", + 16: b"Q", + 25: b"Z", + 8: b"I", + 17: b"R", + 26: b"2", +} + +_b32tab = [v[0] for k, v in sorted(_b32alphabet.items())] +_b32rev = dict([(v[0], k) for k, v in _b32alphabet.items()]) + + +def b32encode(s): + """Encode a byte string using Base32. + + s is the byte string to encode. The encoded byte string is returned. + """ + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + quanta, leftover = divmod(len(s), 5) + # Pad the last quantum with zero bits if necessary + if leftover: + s = s + bytes(5 - leftover) # Don't use += ! + quanta += 1 + encoded = bytearray() + for i in range(quanta): + # c1 and c2 are 16 bits wide, c3 is 8 bits wide. The intent of this + # code is to process the 40 bits in units of 5 bits. So we take the 1 + # leftover bit of c1 and tack it onto c2. Then we take the 2 leftover + # bits of c2 and tack them onto c3. The shifts and masks are intended + # to give us values of exactly 5 bits in width. + c1, c2, c3 = struct.unpack("!HHB", s[i * 5 : (i + 1) * 5]) + c2 += (c1 & 1) << 16 # 17 bits wide + c3 += (c2 & 3) << 8 # 10 bits wide + encoded += bytes( + [ + _b32tab[c1 >> 11], # bits 1 - 5 + _b32tab[(c1 >> 6) & 0x1F], # bits 6 - 10 + _b32tab[(c1 >> 1) & 0x1F], # bits 11 - 15 + _b32tab[c2 >> 12], # bits 16 - 20 (1 - 5) + _b32tab[(c2 >> 7) & 0x1F], # bits 21 - 25 (6 - 10) + _b32tab[(c2 >> 2) & 0x1F], # bits 26 - 30 (11 - 15) + _b32tab[c3 >> 5], # bits 31 - 35 (1 - 5) + _b32tab[c3 & 0x1F], # bits 36 - 40 (1 - 5) + ] + ) + # Adjust for any leftover partial quanta + if leftover == 1: + encoded = encoded[:-6] + b"======" + elif leftover == 2: + encoded = encoded[:-4] + b"====" + elif leftover == 3: + encoded = encoded[:-3] + b"===" + elif leftover == 4: + encoded = encoded[:-1] + b"=" + return bytes(encoded) + + +def b32decode(s, casefold=False, map01=None): + """Decode a Base32 encoded byte string. + + s is the byte string to decode. Optional casefold is a flag + specifying whether a lowercase alphabet is acceptable as input. + For security purposes, the default is False. + + RFC 3548 allows for optional mapping of the digit 0 (zero) to the + letter O (oh), and for optional mapping of the digit 1 (one) to + either the letter I (eye) or letter L (el). The optional argument + map01 when not None, specifies which letter the digit 1 should be + mapped to (when map01 is not None, the digit 0 is always mapped to + the letter O). For security purposes the default is None, so that + 0 and 1 are not allowed in the input. + + The decoded byte string is returned. binascii.Error is raised if + the input is incorrectly padded or if there are non-alphabet + characters present in the input. + """ + s = _bytes_from_decode_data(s) + quanta, leftover = divmod(len(s), 8) + if leftover: + raise binascii.Error("Incorrect padding") + # Handle section 2.4 zero and one mapping. The flag map01 will be either + # False, or the character to map the digit 1 (one) to. It should be + # either L (el) or I (eye). + if map01 is not None: + map01 = _bytes_from_decode_data(map01) + assert len(map01) == 1, repr(map01) + s = _translate(s, _maketrans(b"01", b"O" + map01)) + if casefold: + s = s.upper() + # Strip off pad characters from the right. We need to count the pad + # characters because this will tell us how many null bytes to remove from + # the end of the decoded string. + padchars = s.find(b"=") + if padchars > 0: + padchars = len(s) - padchars + s = s[:-padchars] + else: + padchars = 0 + + # Now decode the full quanta + parts = [] + acc = 0 + shift = 35 + for c in s: + val = _b32rev.get(c) + if val is None: + raise binascii.Error("Non-base32 digit found") + acc += _b32rev[c] << shift + shift -= 5 + if shift < 0: + parts.append(binascii.unhexlify(bytes("%010x" % acc, "ascii"))) + acc = 0 + shift = 35 + # Process the last, partial quanta + last = binascii.unhexlify(bytes("%010x" % acc, "ascii")) + if padchars == 0: + last = b"" # No characters + elif padchars == 1: + last = last[:-1] + elif padchars == 3: + last = last[:-2] + elif padchars == 4: + last = last[:-3] + elif padchars == 6: + last = last[:-4] + else: + raise binascii.Error("Incorrect padding") + parts.append(last) + return b"".join(parts) + + +# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns +# lowercase. The RFC also recommends against accepting input case +# insensitively. +def b16encode(s): + """Encode a byte string using Base16. + + s is the byte string to encode. The encoded byte string is returned. + """ + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + return binascii.hexlify(s).upper() + + +def b16decode(s, casefold=False): + """Decode a Base16 encoded byte string. + + s is the byte string to decode. Optional casefold is a flag + specifying whether a lowercase alphabet is acceptable as input. + For security purposes, the default is False. + + The decoded byte string is returned. binascii.Error is raised if + s were incorrectly padded or if there are non-alphabet characters + present in the string. + """ + s = _bytes_from_decode_data(s) + if casefold: + s = s.upper() + if re.search(b"[^0-9A-F]", s): + raise binascii.Error("Non-base16 digit found") + return binascii.unhexlify(s) + + +# Legacy interface. This code could be cleaned up since I don't believe +# binascii has any line length limitations. It just doesn't seem worth it +# though. The files should be opened in binary mode. + +MAXLINESIZE = 76 # Excluding the CRLF +MAXBINSIZE = (MAXLINESIZE // 4) * 3 + + +def encode(input, output): + """Encode a file; input and output are binary files.""" + while True: + s = input.read(MAXBINSIZE) + if not s: + break + while len(s) < MAXBINSIZE: + ns = input.read(MAXBINSIZE - len(s)) + if not ns: + break + s += ns + line = binascii.b2a_base64(s) + output.write(line) + + +def decode(input, output): + """Decode a file; input and output are binary files.""" + while True: + line = input.readline() + if not line: + break + s = binascii.a2b_base64(line) + output.write(s) + + +def encodebytes(s): + """Encode a bytestring into a bytestring containing multiple lines + of base-64 data.""" + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + pieces = [] + for i in range(0, len(s), MAXBINSIZE): + chunk = s[i : i + MAXBINSIZE] + pieces.append(binascii.b2a_base64(chunk)) + return b"".join(pieces) + + +def encodestring(s): + """Legacy alias of encodebytes().""" + import warnings + + warnings.warn("encodestring() is a deprecated alias, use encodebytes()", DeprecationWarning, 2) + return encodebytes(s) + + +def decodebytes(s): + """Decode a bytestring of base-64 data into a bytestring.""" + if not isinstance(s, bytes_types): + raise TypeError("expected bytes, not %s" % s.__class__.__name__) + return binascii.a2b_base64(s) + + +def decodestring(s): + """Legacy alias of decodebytes().""" + import warnings + + warnings.warn("decodestring() is a deprecated alias, use decodebytes()", DeprecationWarning, 2) + return decodebytes(s) + + +# Usable as a script... +def main(): + """Small main program""" + import sys, getopt + + try: + opts, args = getopt.getopt(sys.argv[1:], "deut") + except getopt.error as msg: + sys.stdout = sys.stderr + print(msg) + print( + """usage: %s [-d|-e|-u|-t] [file|-] + -d, -u: decode + -e: encode (default) + -t: encode and decode string 'Aladdin:open sesame'""" + % sys.argv[0] + ) + sys.exit(2) + func = encode + for o, a in opts: + if o == "-e": + func = encode + if o == "-d": + func = decode + if o == "-u": + func = decode + if o == "-t": + test() + return + if args and args[0] != "-": + with open(args[0], "rb") as f: + func(f, sys.stdout.buffer) + else: + func(sys.stdin.buffer, sys.stdout.buffer) + + +def test(): + s0 = b"Aladdin:open sesame" + print(repr(s0)) + s1 = encodebytes(s0) + print(repr(s1)) + s2 = decodebytes(s1) + print(repr(s2)) + assert s0 == s2 + + +if __name__ == "__main__": + main() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ble_advertising.py b/mixly/boards/default_src/micropython/origin/build/lib/ble_advertising.py new file mode 100644 index 00000000..b0596f36 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ble_advertising.py @@ -0,0 +1,79 @@ +# Helpers for generating BLE advertising payloads. + +from micropython import const +import struct +import bluetooth + +# Advertising payloads are repeated packets of the following form: +# 1 byte data length (N + 1) +# 1 byte type (see constants below) +# N bytes type-specific data + +_ADV_TYPE_FLAGS = const(0x01) +_ADV_TYPE_NAME = const(0x09) +_ADV_TYPE_UUID16_COMPLETE = const(0x3) +_ADV_TYPE_UUID32_COMPLETE = const(0x5) +_ADV_TYPE_UUID128_COMPLETE = const(0x7) +_ADV_TYPE_UUID16_MORE = const(0x2) +_ADV_TYPE_UUID32_MORE = const(0x4) +_ADV_TYPE_UUID128_MORE = const(0x6) +_ADV_TYPE_APPEARANCE = const(0x19) + + +# Generate a payload to be passed to gap_advertise(adv_data=...). +def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0): + payload = bytearray() + + def _append(adv_type, value): + nonlocal payload + payload += struct.pack("BB", len(value) + 1, adv_type) + value + + _append( + _ADV_TYPE_FLAGS, + struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)), + ) + + if name: + _append(_ADV_TYPE_NAME, name.encode()) + + if services: + for uuid in services: + b = bytes(uuid) + if len(b) == 2: + _append(_ADV_TYPE_UUID16_COMPLETE, b) + elif len(b) == 4: + _append(_ADV_TYPE_UUID32_COMPLETE, b) + elif len(b) == 16: + _append(_ADV_TYPE_UUID128_COMPLETE, b) + + # See org.bluetooth.characteristic.gap.appearance.xml + if appearance: + _append(_ADV_TYPE_APPEARANCE, struct.pack(" 5: break + _keys[i] = general[i] + else: + _keys[0] = general + self._ble.gatts_notify(self.conn_handle, self.k_rep, bytes([special & 0xFF, 0]) + _keys) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.k_rep, b'\x00\x00\x00\x00\x00\x00\x00\x00') + + def keyboard_str(self, string, delay=0): + '''键盘发送ASCLL码''' + for char in str(string): + char = max(min(ord(char), 127), 0) + self.keyboard_notify( 0x02 if _KEYCODE[char] >> 7 else 0x00, _KEYCODE[char] & 0x7F) + time.sleep_ms(20 + delay) + + def mouse_notify(self, keys=0, move=(0, 0), wheel=0, release=True): + '''鼠标 按键*3 + 位移 + 滚轮''' + if self.is_connected(): + self._ble.gatts_notify(self.conn_handle, self.m_rep, bytes([keys & 0x0F, move[0] & 0xFF, move[1] & 0xFF, wheel & 0xFF])) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.m_rep, b'\x00\x00\x00\x00') + + def Joystick_notify(self, keys=0, axes=(0, 0), release=False): + '''手柄 按键*8 + 摇杆''' + if self.is_connected(): + self._ble.gatts_notify(self.conn_handle, self.j_rep, bytes([axes[0] & 0xFF, axes[1] & 0xFF, keys & 0xFF])) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.j_rep, b'\x00\x00\x00') + @property + def mac(self): + '''Get mac address''' + return hexlify(self._ble.config('mac')[1]).decode() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ble_hid_keyboard.py b/mixly/boards/default_src/micropython/origin/build/lib/ble_hid_keyboard.py new file mode 100644 index 00000000..4f67ab6a --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ble_hid_keyboard.py @@ -0,0 +1,218 @@ +""" +Bluetooth-HID-Keyboard + +Micropython library for the Bluetooth-HID-Keyboard +======================================================= +#https://github.com/Heerkog/MicroPythonBLEHID + +@dahanzimin From the Mixly Team +""" +import bluetooth +import struct, time +from micropython import const +from ubinascii import hexlify +from ble_advertising import advertising_payload +from bluetooth import UUID, FLAG_READ, FLAG_WRITE ,FLAG_NOTIFY, FLAG_WRITE_NO_RESPONSE + +_IRQ_CENTRAL_CONNECT = const(1) +_IRQ_CENTRAL_DISCONNECT = const(2) +_IRQ_GATTS_WRITE = const(3) +_IRQ_MTU_EXCHANGED = const(21) +_IRQ_CONNECTION_UPDATE = const(27) +_IRQ_GET_SECRET = const(29) +_IRQ_SET_SECRET = const(30) +_IRQ_PASSKEY_ACTION = const(31) +_PASSKEY_ACTION_INPUT = const(2) +_PASSKEY_ACTION_DISP = const(3) +_PASSKEY_ACTION_NUMCMP = const(4) + +_HID_INPUT_REPORT = const(b'\x05\x01\t\x06\xa1\x01\x85\x01u\x01\x95\x08\x05\x07\x19\xe0)\xe7\x15\x00%\x01\x81\x02\x95\x01u\x08\x81\x01\x95\x05u\x01\x05\x08\x19\x01)\x05\x91\x02\x95\x01u\x03\x91\x01\x95\x06u\x08\x15\x00%e\x05\x07\x19\x00)e\x81\x00\xc0') +_KEYCODE = const(b'\x00\x00\x00\x00\x00\x00\x00\x00*+(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x00,\x9e\xb4\xa0\xa1\xa2\xa44\xa6\xa7\xa5\xae6-78\'\x1e\x1f !"#$%&\xb33\xb6.\xb7\xb8\x9f\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d/10\xa3\xad5\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\xaf\xb1\xb0\xb5L') + +_DIS = (UUID(0x180A), ( (UUID(0x2A24), FLAG_READ), + (UUID(0x2A25), FLAG_READ), + (UUID(0x2A26), FLAG_READ), + (UUID(0x2A27), FLAG_READ), + (UUID(0x2A28), FLAG_READ), + (UUID(0x2A29), FLAG_READ), + (UUID(0x2A50), FLAG_READ), ), ) + +_BAS = (UUID(0x180F), ( (UUID(0x2A19), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2904), 0x01),)), ), ) + +_HIDS = (UUID(0x1812), ((UUID(0x2A4A), FLAG_READ), + (UUID(0x2A4B), FLAG_READ), + (UUID(0x2A4C), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), + (UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2908), 0x01 | 0x02),)), + (UUID(0x2A4D), FLAG_READ | FLAG_WRITE, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2908), 0x01 | 0x02),)), + (UUID(0x2A4E), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), ), ) + +class Keyboard: + def __init__(self, name=None, passkey=1234, battery_level=100): + if (name is '') or (name is None): + name = "Mixgo_" + self.mac[-6:].upper() + print("Keyboard name:", name) + + self._ble = bluetooth.BLE() + self._ble.active(True) + self._ble.irq(self._irq) + self._ble.config(gap_name=name) + self._ble.config(mtu=23) + self.device_state = False + self.conn_handle = None + self.passkey = passkey + self.battery_level = battery_level + self.report = b'\x00' + try: + import ble_hid_key + self.keys = ble_hid_key.keys + except: + self.keys = {} + + handles = self._ble.gatts_register_services((_DIS, _BAS, _HIDS)) + self._service_characteristics(handles) + self._payload = advertising_payload(name=name, services=[UUID(0x1812)], appearance=const(961)) + self.advertise() + + def _irq(self, event, data): + # Interrupt request callback function + if event == _IRQ_CENTRAL_CONNECT: + self.conn_handle, _, _ = data + print("Keyboard connected: ", self.conn_handle) + self.device_state = True + elif event == _IRQ_CENTRAL_DISCONNECT: + self.conn_handle = None + conn_handle, addr_type, addr = data + print("Keyboard disconnected: ", conn_handle) + self.advertise() + self.device_state = False + elif event == _IRQ_MTU_EXCHANGED: + conn_handle, mtu = data + self._ble.config(mtu=mtu) + print("MTU exchanged: ", mtu) + elif event == _IRQ_CONNECTION_UPDATE: + self.conn_handle, _, _, _, _ = data + print("Connection update") + elif event == _IRQ_PASSKEY_ACTION: + conn_handle, action, passkey = data + print("Passkey action", conn_handle, action, passkey) + if action == _PASSKEY_ACTION_NUMCMP: + self._ble.gap_passkey(conn_handle, action, False) + elif action == _PASSKEY_ACTION_DISP: + print("Displaying passkey") + self._ble.gap_passkey(conn_handle, action, self.passkey) + elif action == _PASSKEY_ACTION_INPUT: + print(" Prompting for passkey") + self._ble.gap_passkey(conn_handle, action, None) + else: + print("unknown action") + elif event == _IRQ_GATTS_WRITE: + conn_handle, attr_handle = data + self.report = self._ble.gatts_read(attr_handle) + elif event == _IRQ_SET_SECRET: + sec_type, key, value = data + key = sec_type, bytes(key) + value = bytes(value) if value else None + #print("Set secret: ", key, value) + if value is None: + if key in self.keys: + del self.keys[key] + self.key_secrets(self.keys) + return True + else: + return False + else: + self.keys[key] = value + self.key_secrets(self.keys) + return True + elif event == _IRQ_GET_SECRET: + sec_type, index, key = data + #print("Get secret: ", sec_type, index, bytes(key) if key else None) + if key is None: + i = 0 + for (t, _key), value in self.keys.items(): + if t == sec_type: + if i == index: + return value + i += 1 + return None + else: + key = sec_type, bytes(key) + return self.keys.get(key, None) + #else: + #print("Unhandled IRQ event: ", event, data) + + def key_secrets(self, keys={}): + with open("ble_hid_key.py", "w+") as s_f: + s_f.write("keys=" + str(keys) + "\n") + + def _service_characteristics(self, handles): + (h_mod, h_ser, h_fwr, h_hwr, h_swr, h_man, h_pnp) = handles[0] + (self.h_bat, h_ccc, h_bfmt,) = handles[1] + (h_info, h_hid, _, self.h_rep, _, h_d1, _, _, h_d2, h_proto) = handles[2] + + # Write DIS characteristics. + self._ble.gatts_write(h_mod, b'1') + self._ble.gatts_write(h_ser, b'1') + self._ble.gatts_write(h_fwr, b'1') + self._ble.gatts_write(h_hwr, b'1') + self._ble.gatts_write(h_swr, b'1') + self._ble.gatts_write(h_man, b'Homebrew') + self._ble.gatts_write(h_pnp, struct.pack(" 5: break + _keys[i] = general[i] + else: + _keys[0] = general + # Pack the mouse state as described by the input report + self._ble.gatts_notify(self.conn_handle, self.h_rep, bytes([special & 0xFF, 0]) + _keys) + if release: + time.sleep_ms(10) + self._ble.gatts_notify(self.conn_handle, self.h_rep, b'\x00\x00\x00\x00\x00\x00\x00\x00') + + def notify_battery(self, level): + if self.is_connected(): + self.battery_level = max(min(level, 100), 0) + # Notifies the client by writing to the battery level handle. + self._ble.gatts_notify(self.conn_handle, self.h_bat, struct.pack("> 7 else 0x00, _KEYCODE[char] & 0x7F) + time.sleep_ms(20 + delay) + + @property + def mac(self): + '''Get mac address''' + return hexlify(self._ble.config('mac')[1]).decode() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ble_hid_mouse.py b/mixly/boards/default_src/micropython/origin/build/lib/ble_hid_mouse.py new file mode 100644 index 00000000..9f0fef69 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ble_hid_mouse.py @@ -0,0 +1,193 @@ +""" +Bluetooth-HID-Mouse + +Micropython library for the Bluetooth-HID-Mouse +======================================================= +#https://github.com/Heerkog/MicroPythonBLEHID + +@dahanzimin From the Mixly Team +""" +import bluetooth +import struct, time +from micropython import const +from ubinascii import hexlify +from ble_advertising import advertising_payload +from bluetooth import UUID, FLAG_READ, FLAG_WRITE ,FLAG_NOTIFY, FLAG_WRITE_NO_RESPONSE + +_IRQ_CENTRAL_CONNECT = const(1) +_IRQ_CENTRAL_DISCONNECT = const(2) +_IRQ_MTU_EXCHANGED = const(21) +_IRQ_CONNECTION_UPDATE = const(27) +_IRQ_GET_SECRET = const(29) +_IRQ_SET_SECRET = const(30) +_IRQ_PASSKEY_ACTION = const(31) +_PASSKEY_ACTION_INPUT = const(2) +_PASSKEY_ACTION_DISP = const(3) +_PASSKEY_ACTION_NUMCMP = const(4) + +_HID_INPUT_REPORT = const(b'\x05\x01\t\x02\xa1\x01\x85\x01\t\x01\xa1\x00\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x03\x05\x01\t0\t1\t8\x15\x81%\x7fu\x08\x95\x03\x81\x06\xc0\xc0') + +_DIS = (UUID(0x180A), ( (UUID(0x2A24), FLAG_READ), + (UUID(0x2A25), FLAG_READ), + (UUID(0x2A26), FLAG_READ), + (UUID(0x2A27), FLAG_READ), + (UUID(0x2A28), FLAG_READ), + (UUID(0x2A29), FLAG_READ), + (UUID(0x2A50), FLAG_READ), ), ) + +_BAS = (UUID(0x180F), ( (UUID(0x2A19), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2904), 0x01),)), ), ) + +_HIDS = (UUID(0x1812), ((UUID(0x2A4A), FLAG_READ), + (UUID(0x2A4B), FLAG_READ), + (UUID(0x2A4C), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), + (UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, ( + (UUID(0x2902), 0x01 | 0x02), + (UUID(0x2908), 0x01 | 0x02), )), + (UUID(0x2A4E), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), ), ) + +class Mouse: + def __init__(self, name=None, passkey=1234, battery_level=100): + if (name is '') or (name is None): + name = "Mixgo_" + self.mac[-6:].upper() + print("Mouse name:", name) + + self._ble = bluetooth.BLE() + self._ble.active(True) + self._ble.irq(self._irq) + self._ble.config(gap_name=name) + self._ble.config(mtu=23) + self.device_state = False + self.conn_handle = None + self.passkey = passkey + self.battery_level = battery_level + try: + import ble_hid_key + self.keys = ble_hid_key.keys + except: + self.keys = {} + + handles = self._ble.gatts_register_services((_DIS, _BAS, _HIDS)) + self._service_characteristics(handles) + self._payload = advertising_payload(name=name, services=[UUID(0x1812)], appearance=const(962)) + self.advertise() + + def _irq(self, event, data): + # Interrupt request callback function + if event == _IRQ_CENTRAL_CONNECT: + self.conn_handle, _, _ = data + print("Mouse connected: ", self.conn_handle) + self.device_state = True + elif event == _IRQ_CENTRAL_DISCONNECT: + self.conn_handle = None + conn_handle, addr_type, addr = data + print("Mouse disconnected: ", conn_handle) + self.advertise() + self.device_state = False + elif event == _IRQ_MTU_EXCHANGED: + conn_handle, mtu = data + self._ble.config(mtu=mtu) + print("MTU exchanged: ", mtu) + elif event == _IRQ_CONNECTION_UPDATE: + self.conn_handle, _, _, _, _ = data + print("Connection update") + elif event == _IRQ_PASSKEY_ACTION: + conn_handle, action, passkey = data + print("Passkey action", conn_handle, action, passkey) + if action == _PASSKEY_ACTION_NUMCMP: + self._ble.gap_passkey(conn_handle, action, False) + elif action == _PASSKEY_ACTION_DISP: + print("Displaying passkey") + self._ble.gap_passkey(conn_handle, action, self.passkey) + elif action == _PASSKEY_ACTION_INPUT: + print(" Prompting for passkey") + self._ble.gap_passkey(conn_handle, action, None) + else: + print("unknown action") + elif event == _IRQ_SET_SECRET: + sec_type, key, value = data + key = sec_type, bytes(key) + value = bytes(value) if value else None + #print("Set secret: ", key, value) + if value is None: + if key in self.keys: + del self.keys[key] + self.key_secrets(self.keys) + return True + else: + return False + else: + self.keys[key] = value + self.key_secrets(self.keys) + return True + elif event == _IRQ_GET_SECRET: + sec_type, index, key = data + #print("Get secret: ", sec_type, index, bytes(key) if key else None) + if key is None: + i = 0 + for (t, _key), value in self.keys.items(): + if t == sec_type: + if i == index: + return value + i += 1 + return None + else: + key = sec_type, bytes(key) + return self.keys.get(key, None) + #else: + #print("Unhandled IRQ event: ", event, data) + + def key_secrets(self, keys={}): + with open("ble_hid_key.py", "w+") as s_f: + s_f.write("keys=" + str(keys) + "\n") + + def _service_characteristics(self, handles): + (h_mod, h_ser, h_fwr, h_hwr, h_swr, h_man, h_pnp) = handles[0] + (self.h_bat, h_ccc, h_bfmt,) = handles[1] + (h_info, h_hid, h_ctrl, self.h_rep, _, h_d1, h_proto) = handles[2] + + # Write DIS characteristics. + self._ble.gatts_write(h_mod, b'1') + self._ble.gatts_write(h_ser, b'1') + self._ble.gatts_write(h_fwr, b'1') + self._ble.gatts_write(h_hwr, b'1') + self._ble.gatts_write(h_swr, b'1') + self._ble.gatts_write(h_man, b'Homebrew') + self._ble.gatts_write(h_pnp, struct.pack(" 0 + + def _advertise(self, interval_us=500000): + print("Starting advertising") + self._ble.gap_advertise(interval_us, adv_data=self._payload) + + def recv(self, callback= None): + if callback: + self._write_callback = callback + else: + write_data=self._write_data + self._write_data=None + return write_data + + @property + def mac(self): + '''Get mac address''' + return hexlify(self._ble.config('mac')[1]).decode() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ble_uart_peripheral.py b/mixly/boards/default_src/micropython/origin/build/lib/ble_uart_peripheral.py new file mode 100644 index 00000000..3009a663 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ble_uart_peripheral.py @@ -0,0 +1,86 @@ +""" +Bluetooth-uart-Peripheral + +Micropython library for the Bluetooth-uart-Peripheral +======================================================= +#Preliminary composition 202200628 +#https://github.com/micropython/micropython/tree/master/examples/bluetooth + +dahanzimin From the Mixly Team +""" + +import bluetooth +from ble_advertising import advertising_payload +from micropython import const + +_IRQ_CENTRAL_CONNECT = const(1) +_IRQ_CENTRAL_DISCONNECT = const(2) +_IRQ_GATTS_WRITE = const(3) + +_FLAG_READ = const(0x0002) +_FLAG_WRITE_NO_RESPONSE = const(0x0004) +_FLAG_WRITE = const(0x0008) +_FLAG_NOTIFY = const(0x0010) + +_UART_UUID = bluetooth.UUID("0000fff0-0000-1000-8000-00805f9b34fb") +_UART_TX = (bluetooth.UUID("0000fff1-0000-1000-8000-00805f9b34fb"),_FLAG_READ | _FLAG_NOTIFY,) +_UART_RX = (bluetooth.UUID("0000fff2-0000-1000-8000-00805f9b34fb"),_FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,) +_UART_SERVICE = (_UART_UUID,(_UART_TX, _UART_RX),) + +class BLEUART: + def __init__(self, name="mpy-uart", rxbuf=100): + self._ble = bluetooth.BLE() + self._ble.active(True) + self._ble.irq(self._irq) + ((self._tx_handle, self._rx_handle),) = self._ble.gatts_register_services((_UART_SERVICE,)) + self._ble.gatts_set_buffer(self._rx_handle, rxbuf, True) + self._connections = set() + self._rx_buffer = bytearray() + self._handler = None + self._payload = advertising_payload(name=name, services=[_UART_UUID]) + self._advertise() + + def irq(self, handler): + self._handler = handler + + def _irq(self, event, data): + # Track connections so we can send notifications. + if event == _IRQ_CENTRAL_CONNECT: + conn_handle, _, _ = data + print("Bluetooth connected") + self._connections.add(conn_handle) + elif event == _IRQ_CENTRAL_DISCONNECT: + conn_handle, _, _ = data + print("Bluetooth disconnected") + if conn_handle in self._connections: + self._connections.remove(conn_handle) + # Start advertising again to allow a new connection. + self._advertise() + elif event == _IRQ_GATTS_WRITE: + conn_handle, value_handle = data + if conn_handle in self._connections and value_handle == self._rx_handle: + self._rx_buffer += self._ble.gatts_read(self._rx_handle) + if self._handler: + self._handler() + + def any(self): + return len(self._rx_buffer) + + def read(self, sz=None): + if not sz: + sz = len(self._rx_buffer) + result = self._rx_buffer[0:sz] + self._rx_buffer = self._rx_buffer[sz:] + return result + + def write(self, data): + for conn_handle in self._connections: + self._ble.gatts_notify(conn_handle, self._tx_handle, data) + + def close(self): + for conn_handle in self._connections: + self._ble.gap_disconnect(conn_handle) + self._connections.clear() + + def _advertise(self, interval_us=500000): + self._ble.gap_advertise(interval_us, adv_data=self._payload) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ble_uart_repl.py b/mixly/boards/default_src/micropython/origin/build/lib/ble_uart_repl.py new file mode 100644 index 00000000..f88d99ab --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ble_uart_repl.py @@ -0,0 +1,67 @@ +# Proof-of-concept of a REPL over BLE UART. +# Set the EoL characters to \r\n. + +import io +import os +from machine import Timer +from micropython import schedule +from ble_uart_peripheral import BLEUART + +_MP_STREAM_POLL = const(3) +_MP_STREAM_POLL_RD = const(0x0001) + +# Batch writes into 50ms intervals. +Define_timer = Timer(2) + +def schedule_in(handler, delay_ms): + def _wrap(_arg): + handler() + if Define_timer: + Define_timer.init(mode=Timer.ONE_SHOT, period=delay_ms, callback=_wrap) + else: + schedule(_wrap, None) + +# Simple buffering stream to support the dupterm requirements. +class BLEUARTStream(io.IOBase): + def __init__(self, name="mpy-repl"): + self._uart = BLEUART(name) + self._tx_buf = bytearray() + self._uart.irq(self._on_rx) + + def _on_rx(self): + if hasattr(os, "dupterm_notify"): + os.dupterm_notify(None) + + def read(self, sz=None): + return self._uart.read(sz) + + def readinto(self, buf): + avail = self._uart.read(len(buf)) + if not avail: + return None + for i in range(len(avail)): + buf[i] = avail[i] + return len(avail) + + def ioctl(self, op, arg): + if op == _MP_STREAM_POLL: + if self._uart.any(): + return _MP_STREAM_POLL_RD + return 0 + + def _flush(self): + data = self._tx_buf[0:100] + self._tx_buf = self._tx_buf[100:] + self._uart.write(data) + if self._tx_buf: + schedule_in(self._flush, 50) + + def write(self, buf): + empty = not self._tx_buf + self._tx_buf += buf + if empty: + schedule_in(self._flush, 50) + +def start(ble_name="mpy-repl"): + stream = BLEUARTStream(name=ble_name) + os.dupterm(stream) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/blynklib.py b/mixly/boards/default_src/micropython/origin/build/lib/blynklib.py new file mode 100644 index 00000000..46f88977 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/blynklib.py @@ -0,0 +1,377 @@ +# Copyright (c) 2019-2020 Anton Morozenko +# Copyright (c) 2015-2019 Volodymyr Shymanskyy. +# See the file LICENSE for copying permission. + +__version__ = '0.2.6' + +import usocket as socket +import utime as time +import ustruct as struct +import uselect as select +from micropython import const + +ticks_ms = time.ticks_ms +sleep_ms = time.sleep_ms + +IOError = OSError + +LOGO = """ + ___ __ __ + / _ )/ /_ _____ / /__ + / _ / / // / _ \\/ '_/ + /____/_/\\_, /_//_/_/\\_\\ + /___/ for Python v{}\n""".format(__version__) + + +def stub_log(*args): + pass + + +class BlynkError(Exception): + pass + + +class RedirectError(Exception): + def __init__(self, server, port): + self.server = server + self.port = port + + +class Protocol(object): + MSG_RSP = const(0) + MSG_LOGIN = const(2) + MSG_PING = const(6) + MSG_TWEET = const(12) + MSG_EMAIL = const(13) + MSG_NOTIFY = const(14) + MSG_BRIDGE = const(15) + MSG_HW_SYNC = const(16) + MSG_INTERNAL = const(17) + MSG_PROPERTY = const(19) + MSG_HW = const(20) + MSG_REDIRECT = const(41) + MSG_HEAD_LEN = const(5) + + STATUS_INVALID_TOKEN = const(9) + STATUS_OK = const(200) + VPIN_MAX_NUM = const(32) + + _msg_id = 1 + + def _get_msg_id(self, **kwargs): + if 'msg_id' in kwargs: + return kwargs['msg_id'] + self._msg_id += const(1) + return self._msg_id if self._msg_id <= const(0xFFFF) else const(1) + + def _pack_msg(self, msg_type, *args, **kwargs): + data = ('\0'.join([str(curr_arg) for curr_arg in args])).encode('utf-8') + return struct.pack('!BHH', msg_type, self._get_msg_id(**kwargs), len(data)) + data + + def parse_response(self, rsp_data, msg_buffer): + msg_args = [] + msg_len = 0 + try: + msg_type, msg_id, h_data = struct.unpack('!BHH', rsp_data[:self.MSG_HEAD_LEN]) + msg_len = self.MSG_HEAD_LEN + h_data + except Exception as p_err: + raise BlynkError('Message parse error: {}'.format(p_err)) + if msg_id == 0: + raise BlynkError('invalid msg_id == 0') + elif h_data >= msg_buffer: + raise BlynkError('Command too long. Length = {}'.format(h_data)) + elif msg_type in (self.MSG_RSP, self.MSG_PING): + pass + elif msg_type in (self.MSG_HW, self.MSG_BRIDGE, self.MSG_INTERNAL, self.MSG_REDIRECT): + msg_body = rsp_data[self.MSG_HEAD_LEN: msg_len] + msg_args = [itm.decode('utf-8') for itm in msg_body.split(b'\0')] + else: + raise BlynkError("Unknown message type: '{}'".format(msg_type)) + return msg_type, msg_id, h_data, msg_args, msg_len + + def heartbeat_msg(self, heartbeat, rcv_buffer): + return self._pack_msg(self.MSG_INTERNAL, 'ver', __version__, 'buff-in', rcv_buffer, 'h-beat', heartbeat, + 'dev', 'mpython') + + def login_msg(self, token): + return self._pack_msg(self.MSG_LOGIN, token) + + def ping_msg(self): + return self._pack_msg(self.MSG_PING) + + def response_msg(self, *args, **kwargs): + return self._pack_msg(self.MSG_RSP, *args, **kwargs) + + def virtual_write_msg(self, v_pin, *val): + return self._pack_msg(self.MSG_HW, 'vw', v_pin, *val) + + def virtual_sync_msg(self, *pins): + return self._pack_msg(self.MSG_HW_SYNC, 'vr', *pins) + + def email_msg(self, to, subject, body): + return self._pack_msg(self.MSG_EMAIL, to, subject, body) + + def tweet_msg(self, msg): + return self._pack_msg(self.MSG_TWEET, msg) + + def notify_msg(self, msg): + return self._pack_msg(self.MSG_NOTIFY, msg) + + def set_property_msg(self, pin, prop, *val): + return self._pack_msg(self.MSG_PROPERTY, pin, prop, *val) + + def internal_msg(self, *args): + return self._pack_msg(self.MSG_INTERNAL, *args) + + +class Connection(Protocol): + SOCK_MAX_TIMEOUT = const(5) + SOCK_TIMEOUT = 0.05 + EAGAIN = const(11) + ETIMEDOUT = const(60) + RETRIES_TX_DELAY = const(2) + RETRIES_TX_MAX_NUM = const(3) + RECONNECT_SLEEP = const(1) + TASK_PERIOD_RES = const(50) + DISCONNECTED = const(0) + CONNECTING = const(1) + AUTHENTICATING = const(2) + AUTHENTICATED = const(3) + + _state = None + _socket = None + _last_rcv_time = 0 + _last_ping_time = 0 + _last_send_time = 0 + + def __init__(self, token, server='blynk-cloud.com', port=80, heartbeat=10, rcv_buffer=1024, log=stub_log): + self.token = token + self.server = server + self.port = port + self.heartbeat = heartbeat + self.rcv_buffer = rcv_buffer + self.log = log + + def _set_socket_timeout(self, timeout): + if getattr(self._socket, 'settimeout', None): + self._socket.settimeout(timeout) + else: + p = select.poll() + p.register(self._socket) + p.poll(int(timeout * const(1000))) + + def send(self, data): + retries = self.RETRIES_TX_MAX_NUM + while retries > 0: + try: + retries -= 1 + self._last_send_time = ticks_ms() + return self._socket.send(data) + except (IOError, OSError): + sleep_ms(self.RETRIES_TX_DELAY) + + def receive(self, length, timeout): + d_buff = b'' + try: + self._set_socket_timeout(timeout) + d_buff += self._socket.recv(length) + if len(d_buff) >= length: + d_buff = d_buff[:length] + return d_buff + except (IOError, OSError) as err: + if str(err) == 'timed out': + return b'' + if str(self.EAGAIN) in str(err) or str(self.ETIMEDOUT) in str(err): + return b'' + raise + + def is_server_alive(self): + now = ticks_ms() + h_beat_ms = self.heartbeat * const(1000) + rcv_delta = time.ticks_diff(now, self._last_rcv_time) + ping_delta = time.ticks_diff(now, self._last_ping_time) + send_delta = time.ticks_diff(now, self._last_send_time) + if rcv_delta > h_beat_ms + (h_beat_ms // const(2)): + return False + if (ping_delta > h_beat_ms // const(10)) and (send_delta > h_beat_ms or rcv_delta > h_beat_ms): + self.send(self.ping_msg()) + self.log('Heartbeat time: {}'.format(now)) + self._last_ping_time = now + return True + + def _get_socket(self): + try: + self._state = self.CONNECTING + self._socket = socket.socket() + self._socket.connect(socket.getaddrinfo(self.server, self.port)[0][-1]) + self._set_socket_timeout(self.SOCK_TIMEOUT) + self.log('Connected to server') + except Exception as g_exc: + raise BlynkError('Server connection failed: {}'.format(g_exc)) + + def _authenticate(self): + self.log('Authenticating device...') + self._state = self.AUTHENTICATING + self.send(self.login_msg(self.token)) + rsp_data = self.receive(self.rcv_buffer, self.SOCK_MAX_TIMEOUT) + if not rsp_data: + raise BlynkError('Auth stage timeout') + msg_type, _, status, args, _ = self.parse_response(rsp_data, self.rcv_buffer) + if status != self.STATUS_OK: + if status == self.STATUS_INVALID_TOKEN: + raise BlynkError('Invalid Auth Token') + if msg_type == self.MSG_REDIRECT: + raise RedirectError(*args) + raise BlynkError('Auth stage failed. Status={}'.format(status)) + self._state = self.AUTHENTICATED + self.log('Access granted') + + def _set_heartbeat(self): + self.send(self.heartbeat_msg(self.heartbeat, self.rcv_buffer)) + rcv_data = self.receive(self.rcv_buffer, self.SOCK_MAX_TIMEOUT) + if not rcv_data: + raise BlynkError('Heartbeat stage timeout') + _, _, status, _, _ = self.parse_response(rcv_data, self.rcv_buffer) + if status != self.STATUS_OK: + raise BlynkError('Set heartbeat returned code={}'.format(status)) + self.log('Heartbeat = {} sec. MaxCmdBuffer = {} bytes'.format(self.heartbeat, self.rcv_buffer)) + + def connected(self): + return True if self._state == self.AUTHENTICATED else False + + +class Blynk(Connection): + _CONNECT_TIMEOUT = const(30) # 30sec + _VPIN_WILDCARD = '*' + _VPIN_READ = 'read v' + _VPIN_WRITE = 'write v' + _INTERNAL = 'internal_' + _CONNECT = 'connect' + _DISCONNECT = 'disconnect' + _VPIN_READ_ALL = '{}{}'.format(_VPIN_READ, _VPIN_WILDCARD) + _VPIN_WRITE_ALL = '{}{}'.format(_VPIN_WRITE, _VPIN_WILDCARD) + _events = {} + + def __init__(self, token, **kwargs): + Connection.__init__(self, token, **kwargs) + self._start_time = ticks_ms() + self._last_rcv_time = ticks_ms() + self._last_send_time = ticks_ms() + self._last_ping_time = ticks_ms() + self._state = self.DISCONNECTED + print(LOGO) + + def connect(self, timeout=_CONNECT_TIMEOUT): + end_time = time.time() + timeout + while not self.connected(): + if self._state == self.DISCONNECTED: + try: + self._get_socket() + self._authenticate() + self._set_heartbeat() + self._last_rcv_time = ticks_ms() + self.log('Registered events: {}\n'.format(list(self._events.keys()))) + self.call_handler(self._CONNECT) + return True + except BlynkError as b_err: + self.disconnect(b_err) + sleep_ms(self.TASK_PERIOD_RES) + except RedirectError as r_err: + self.disconnect() + self.server = r_err.server + self.port = r_err.port + sleep_ms(self.TASK_PERIOD_RES) + if time.time() >= end_time: + return False + + def disconnect(self, err_msg=None): + self.call_handler(self._DISCONNECT) + if self._socket: + self._socket.close() + self._state = self.DISCONNECTED + if err_msg: + self.log('[ERROR]: {}\nConnection closed'.format(err_msg)) + time.sleep(self.RECONNECT_SLEEP) + + def virtual_write(self, v_pin, *val): + return self.send(self.virtual_write_msg(v_pin, *val)) + + def virtual_sync(self, *v_pin): + return self.send(self.virtual_sync_msg(*v_pin)) + + def email(self, to, subject, body): + return self.send(self.email_msg(to, subject, body)) + + def tweet(self, msg): + return self.send(self.tweet_msg(msg)) + + def notify(self, msg): + return self.send(self.notify_msg(msg)) + + def set_property(self, v_pin, property_name, *val): + return self.send(self.set_property_msg(v_pin, property_name, *val)) + + def internal(self, *args): + return self.send(self.internal_msg(*args)) + + def handle_event(blynk, event_name): + class Deco(object): + def __init__(self, func): + self.func = func + # wildcard 'read V*' and 'write V*' events handling + if str(event_name).lower() in (blynk._VPIN_READ_ALL, blynk._VPIN_WRITE_ALL): + event_base_name = str(event_name).split(blynk._VPIN_WILDCARD)[0] + for i in range(blynk.VPIN_MAX_NUM + 1): + blynk._events['{}{}'.format(event_base_name.lower(), i)] = func + else: + blynk._events[str(event_name).lower()] = func + + def __call__(self): + return self.func() + + return Deco + + def call_handler(self, event, *args, **kwargs): + if event in self._events.keys(): + self.log("Event: ['{}'] -> {}".format(event, args)) + self._events[event](*args, **kwargs) + + def process(self, msg_type, msg_id, msg_len, msg_args): + if msg_type == self.MSG_RSP: + self.log('Response status: {}'.format(msg_len)) + elif msg_type == self.MSG_PING: + self.send(self.response_msg(self.STATUS_OK, msg_id=msg_id)) + elif msg_type in (self.MSG_HW, self.MSG_BRIDGE, self.MSG_INTERNAL): + if msg_type == self.MSG_INTERNAL: + self.call_handler("{}{}".format(self._INTERNAL, msg_args[0]), msg_args[1:]) + elif len(msg_args) >= const(3) and msg_args[0] == 'vw': + self.call_handler("{}{}".format(self._VPIN_WRITE, msg_args[1]), int(msg_args[1]), msg_args[2:]) + elif len(msg_args) == const(2) and msg_args[0] == 'vr': + self.call_handler("{}{}".format(self._VPIN_READ, msg_args[1]), int(msg_args[1])) + + def read_response(self, timeout=0.5): + end_time = time.ticks_ms() + int(timeout * const(1000)) + while time.ticks_diff(end_time, time.ticks_ms()) > 0: + rsp_data = self.receive(self.rcv_buffer, self.SOCK_TIMEOUT) + if rsp_data: + self._last_rcv_time = ticks_ms() + while rsp_data: + msg_type, msg_id, h_data, msg_args, msg_len = self.parse_response(rsp_data, self.rcv_buffer) + self.process(msg_type, msg_id, h_data, msg_args) + rsp_data = rsp_data[msg_len:] + + def run(self): + if not self.connected(): + self.connect() + else: + try: + self.read_response(timeout=self.SOCK_TIMEOUT) + if not self.is_server_alive(): + self.disconnect('Server is offline') + except KeyboardInterrupt: + raise + except BlynkError as b_err: + self.log(b_err) + self.disconnect() + except Exception as g_exc: + self.log(g_exc) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/blynktimer.py b/mixly/boards/default_src/micropython/origin/build/lib/blynktimer.py new file mode 100644 index 00000000..704a3911 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/blynktimer.py @@ -0,0 +1,133 @@ +# Copyright (c) 2019-2020 Anton Morozenko +""" +Polling timers for functions. +Registers timers and performs run once or periodical function execution after defined time intervals. +""" +# select.select call used as polling waiter where it is possible +# cause time.sleep sometimes may load CPU up to 100% with small polling wait interval +try: + # cpython + import time + import select + + polling_wait = lambda x: select.select([], [], [], x) + polling_wait(0.01) +except OSError: + # windows case where select.select call fails + polling_wait = lambda x: time.sleep(x) + +except ImportError: + # micropython + import utime as time + + try: + from uselect import select as s_select + + polling_wait = lambda x: s_select([], [], [], x) + except ImportError: + # case when micropython port does not support select.select + polling_wait = lambda x: time.sleep(x) + +WAIT_SEC = 0.05 +MAX_TIMERS = 16 +DEFAULT_INTERVAL = 10 + + +class TimerError(Exception): + pass + + +class Timer(object): + timers = {} + + def __init__(self, no_timers_err=True): + self.no_timers_err = no_timers_err + + def _get_func_name(self, obj): + """retrieves a suitable name for a function""" + if hasattr(obj, 'func'): + # handles nested decorators + return self._get_func_name(obj.func) + # simply returns 'timer' if on port without function attrs + return getattr(obj, '__name__', 'timer') + + def register(blynk, *args, **kwargs): + # kwargs with defaults are used cause PEP 3102 no supported by Python2 + interval = kwargs.pop('interval', DEFAULT_INTERVAL) + run_once = kwargs.pop('run_once', False) + stopped = kwargs.pop('stopped', False) + + class Deco(object): + def __init__(self, func): + self.func = func + if len(list(Timer.timers.keys())) >= MAX_TIMERS: + raise TimerError('Max allowed timers num={}'.format(MAX_TIMERS)) + _timer = _Timer(interval, func, run_once, stopped, *args, **kwargs) + Timer.timers['{}_{}'.format(len(list(Timer.timers.keys())), blynk._get_func_name(func))] = _timer + + def __call__(self, *f_args, **f_kwargs): + return self.func(*f_args, **f_kwargs) + + return Deco + + @staticmethod + def stop(t_id): + timer = Timer.timers.get(t_id, None) + if timer is None: + raise TimerError('Timer id={} not found'.format(t_id)) + Timer.timers[t_id].stopped = True + + @staticmethod + def start(t_id): + timer = Timer.timers.get(t_id, None) + if timer is None: + raise TimerError('Timer id={} not found'.format(t_id)) + Timer.timers[t_id].stopped = False + Timer.timers[t_id].fire_time = None + Timer.timers[t_id].fire_time_prev = None + + @staticmethod + def is_stopped(t_id): + timer = Timer.timers.get(t_id, None) + if timer is None: + raise TimerError('Timer id={} not found'.format(t_id)) + return timer.stopped + + def get_timers(self): + states = {True: 'Stopped', False: 'Running'} + return {k: states[v.stopped] for k, v in self.timers.items()} + + def run(self): + polling_wait(WAIT_SEC) + timers_intervals = [curr_timer.run() for curr_timer in Timer.timers.values() if not curr_timer.stopped] + if not timers_intervals and self.no_timers_err: + raise TimerError('Running timers not found') + return timers_intervals + + +class _Timer(object): + def __init__(self, interval, deco, run_once, stopped, *args, **kwargs): + self.interval = interval + self.deco = deco + self.args = args + self.run_once = run_once + self.kwargs = kwargs + self.fire_time = None + self.fire_time_prev = None + self.stopped = stopped + + def run(self): + timer_real_interval = 0 + if self.fire_time is None: + self.fire_time = time.time() + self.interval + if self.fire_time_prev is None: + self.fire_time_prev = time.time() + curr_time = time.time() + if curr_time >= self.fire_time: + self.deco(*self.args, **self.kwargs) + if self.run_once: + self.stopped = True + timer_real_interval = curr_time - self.fire_time_prev + self.fire_time_prev = self.fire_time + self.fire_time = curr_time + self.interval + return timer_real_interval diff --git a/mixly/boards/default_src/micropython/origin/build/lib/bmp280.py b/mixly/boards/default_src/micropython/origin/build/lib/bmp280.py new file mode 100644 index 00000000..02d2cbd5 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/bmp280.py @@ -0,0 +1,162 @@ +from ustruct import unpack as unp +import utime + +# Power Modes +NORMAL = 0 +BMP280_TEMP_OS_SKIP = 0 +BMP280_TEMP_OS_1 = 1 +BMP280_TEMP_OS_2 = 2 +BMP280_TEMP_OS_4 = 3 +BMP280_TEMP_OS_8 = 4 +BMP280_TEMP_OS_16 = 5 +BMP280_PRES_OS_SKIP = 0 +BMP280_PRES_OS_1 = 1 +BMP280_PRES_OS_2 = 2 +BMP280_PRES_OS_4 = 3 +BMP280_PRES_OS_8 = 4 +BMP280_PRES_OS_16 = 5 +# BMP280 Temperature Registers +BMP280_REGISTER_DIG_T1 = 0x88 +BMP280_REGISTER_DIG_T2 = 0x8A +BMP280_REGISTER_DIG_T3 = 0x8C +# BMP280 Pressure Registers +BMP280_REGISTER_DIG_P1 = 0x8E +BMP280_REGISTER_DIG_P2 = 0x90 +BMP280_REGISTER_DIG_P3 = 0x92 +BMP280_REGISTER_DIG_P4 = 0x94 +BMP280_REGISTER_DIG_P5 = 0x96 +BMP280_REGISTER_DIG_P6 = 0x98 +BMP280_REGISTER_DIG_P7 = 0x9A +BMP280_REGISTER_DIG_P8 = 0x9C +BMP280_REGISTER_DIG_P9 = 0x9E +BMP280_REGISTER_ID = 0xD0 +BMP280_REGISTER_RESET = 0xE0 +BMP280_REGISTER_STATUS = 0xF3 +BMP280_REGISTER_CONTROL = 0xF4 +BMP280_REGISTER_CONFIG = 0xF5 # IIR filter config +BMP280_REGISTER_DATA = 0xF7 + +class BMP280: + def __init__(self, i2c_bus, addr=0x77): + self._bmp_i2c = i2c_bus + self._i2c_addr = addr + self.chip_id = self._read(BMP280_REGISTER_ID, 2) + + self._T1 = unp(' self._new_read_ms: + self._last_read_ts = now + r = self._t_os + (self._p_os << 3) + (1 << 6) + self._write(BMP280_REGISTER_CONTROL, r) + utime.sleep_ms(100) # TODO calc sleep + d = self._read(BMP280_REGISTER_DATA, 6) # read all data at once (as by spec) + self._p_raw = (d[0] << 12) + (d[1] << 4) + (d[2] >> 4) + self._t_raw = (d[3] << 12) + (d[4] << 4) + (d[5] >> 4) + self._t_fine = 0 + self._t = 0 + self._p = 0 + + def load_test_calibration(self): + self._T1 = 27504 + self._T2 = 26435 + self._T3 = -1000 + self._P1 = 36477 + self._P2 = -10685 + self._P3 = 3024 + self._P4 = 2855 + self._P5 = 140 + self._P6 = -7 + self._P7 = 15500 + self._P8 = -14600 + self._P9 = 6000 + + def load_test_data(self): + self._t_raw = 519888 + self._p_raw = 415148 + + def print_calibration(self): + print("T1: {} {}".format(self._T1, type(self._T1))) + print("T2: {} {}".format(self._T2, type(self._T2))) + print("T3: {} {}".format(self._T3, type(self._T3))) + print("P1: {} {}".format(self._P1, type(self._P1))) + print("P2: {} {}".format(self._P2, type(self._P2))) + print("P3: {} {}".format(self._P3, type(self._P3))) + print("P4: {} {}".format(self._P4, type(self._P4))) + print("P5: {} {}".format(self._P5, type(self._P5))) + print("P6: {} {}".format(self._P6, type(self._P6))) + print("P7: {} {}".format(self._P7, type(self._P7))) + print("P8: {} {}".format(self._P8, type(self._P8))) + print("P9: {} {}".format(self._P9, type(self._P9))) + + def _calc_t_fine(self): + # From datasheet page 22 + self._gauge() + if self._t_fine == 0: + var1 = (((self._t_raw >> 3) - (self._T1 << 1)) * self._T2) >> 11 + var2 = (((((self._t_raw >> 4) - self._T1) * ((self._t_raw >> 4) - self._T1)) >> 12) * self._T3) >> 14 + self._t_fine = var1 + var2 + + # @property + def get_BMP_temperature(self): + self._calc_t_fine() + if self._t == 0: + self._t = ((self._t_fine * 5 + 128) >> 8) / 100. + return self._t + + # @property + def get_BMP_pressure(self): + # From datasheet page 22 + self._calc_t_fine() + if self._p == 0: + var1 = self._t_fine - 128000 + var2 = var1 * var1 * self._P6 + var2 = var2 + ((var1 * self._P5) << 17) + var2 = var2 + (self._P4 << 35) + var1 = ((var1 * var1 * self._P3) >> 8) + ((var1 * self._P2) << 12) + var1 = (((1 << 47) + var1) * self._P1) >> 33 + + if var1 == 0: + return 0 + + p = 1048576 - self._p_raw + p = int((((p << 31) - var2) * 3125) / var1) + var1 = (self._P9 * (p >> 13) * (p >> 13)) >> 25 + var2 = (self._P8 * p) >> 19 + + p = ((p + var1 + var2) >> 8) + (self._P7 << 4) + self._p = p / 256.0 + return self._p diff --git a/mixly/boards/default_src/micropython/origin/build/lib/cbr817.py b/mixly/boards/default_src/micropython/origin/build/lib/cbr817.py new file mode 100644 index 00000000..37d93cf3 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/cbr817.py @@ -0,0 +1,117 @@ +""" +CBR817 + +MicroPython library for the CBR817 (Microwave radar sensor) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from machine import Pin +from micropython import const + +CBR_ADDRESS = const(0x71) +CBR_OP_SET = const(0x02) +CBR_TX_RF = const(0x03) +CBR_POWER = const(0x04) +CBR_LIGHT = const(0x0B) +CBR_REG_CTR1 = const(0X13) +CBR_SENSOR_THR = const(0X18) +CBR_NOISE_THR = const(0X1A) +CBR_TRIGER = const(0x1C) +CBR_DELAY_TIM = const(0X1D) +CBR_LOCK_TIM = const(0X20) +CBR_SEL_REG = const(0x23) +CBR_REG_CTR2 = const(0X24) +CBR_FILTER = const(0x2A) +CBR_RESULT = const(0x81) + +class CBR817: + def __init__(self, i2c_bus, addr=CBR_ADDRESS, tx_power=3, threshold=5000, noise=256, delay=500, lock=500): + self._device = i2c_bus + self._address = addr + + self._configure() + self.tx_power(tx_power) + self.threshold(threshold) + self.noise(noise) + self.delay_ms(delay) + self.lock_ms(lock) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address, reg, val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes <= 1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _wake(self): + '''Wake up from low power consumption''' + try: + self._wreg(CBR_SEL_REG, 0xC0) + except : + pass + + def threshold(self, value=None): + self._wake() + if value is None: + return self._rreg(CBR_SENSOR_THR) | self._rreg(CBR_SENSOR_THR + 1) << 8 + else: + self._wreg(CBR_SENSOR_THR, value & 0xFF) + self._wreg(CBR_SENSOR_THR + 1, (value >> 8) & 0xFF) + + def noise(self, value=None): + self._wake() + if value is None: + return self._rreg(CBR_NOISE_THR) | self._rreg(CBR_NOISE_THR + 1) << 8 + else: + self._wreg(CBR_NOISE_THR, value & 0xFF) + self._wreg(CBR_NOISE_THR + 1, (value >> 8) & 0xFF) + + def delay_ms(self, value=None): + self._wake() + if value is None: + return round((self._rreg(CBR_DELAY_TIM) | self._rreg(CBR_DELAY_TIM + 1) << 8 | self._rreg(CBR_DELAY_TIM + 2) << 16) / 32) + else: + value = value * 32 + self._wreg(CBR_DELAY_TIM, value & 0xFF) + self._wreg(CBR_DELAY_TIM + 1, (value >> 8) & 0xFF) + self._wreg(CBR_DELAY_TIM + 2, (value >> 16) & 0xFF) + + def lock_ms(self, value=None): + self._wake() + if value is None: + return round((self._rreg(CBR_LOCK_TIM) | self._rreg(CBR_LOCK_TIM + 1) << 8 | self._rreg(CBR_LOCK_TIM + 2) << 16) // 32) + else: + value = value * 32 + self._wreg(CBR_LOCK_TIM, value & 0xFF) + self._wreg(CBR_LOCK_TIM + 1, (value >> 8) & 0xFF) + self._wreg(CBR_LOCK_TIM + 2, (value >> 16) & 0xFF) + + def tx_power(self, value=None): + self._wake() + if value is None: + return self._rreg(CBR_TX_RF) & 0x07 + else: + self._wreg(CBR_TX_RF, (value & 0x07) | 0x30) + + def _configure(self): + self._wake() + self._wreg(CBR_SEL_REG, 0xC0) #唤醒射频芯片 + _star = time.ticks_ms() + while self._rreg(CBR_SEL_REG) != 0xC0: + self._wreg(CBR_SEL_REG, 0xC0) + time.sleep_us(10) + if time.ticks_diff(time.ticks_ms(), _star) >= 200: + raise AttributeError("Cannot find a CBR817") + self._wreg(CBR_TRIGER, 0x55) #连续检测 + self._wreg(CBR_LIGHT, 0x12) #关闭光敏 + self._wreg(CBR_POWER, 0xA0) #功耗全供电 + self._wreg(CBR_FILTER, 0x0F) #打开滤波器 + self._wreg(CBR_OP_SET, 0x5C) #单运放,0.5uA电流 + self._wreg(CBR_REG_CTR1, 0X61) #感应门限和噪声门限改寄存器控制 + self._wreg(CBR_REG_CTR2, 0X60) #延时时间和闭锁时间改寄存器控制 + + def result(self): + self._wake() + return bool(self._rreg(CBR_RESULT) & 0x20) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/cc_g1.py b/mixly/boards/default_src/micropython/origin/build/lib/cc_g1.py new file mode 100644 index 00000000..998854ea --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/cc_g1.py @@ -0,0 +1,85 @@ +""" +CC_G1 + +Micropython library for the CC_G1(Remote control handle) +======================================================= + +#Preliminary composition 20231222 + +@dahanzimin From the Mixly Team +""" +from micropython import const +from machine import Pin,SoftI2C + +_CC_G1_ADDRESS = const(0x27) +_CC_G1_ID = const(0x00) +_CC_G1_VBAT = const(0x01) +_CC_G1_ADC = const(0x03) +_CC_G1_KEY = const(0x07) + +class Handle: + def __init__(self, i2c_bus, addr=_CC_G1_ADDRESS): + self._i2c=i2c_bus + self._addr = addr + if self._rreg(_CC_G1_ID)!= 0x27: + raise AttributeError("Cannot find a CC_G1") + + def _wreg(self, reg, val): + '''Write memory address''' + try: + self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little')) + except: + return 0 + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + try: + self._i2c.writeto(self._addr, reg.to_bytes(1, 'little')) + return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes<=1 else self._i2c.readfrom(self._addr, nbytes)[0:nbytes] + except: + return 0 + + def read_bat(self, ratio=5/1023): + '''Read battery power''' + vbat = self._rreg(_CC_G1_VBAT)<<2 | self._rreg(_CC_G1_VBAT+1)>>6 + return round(vbat*ratio, 2) + + def read_joystick(self, ratio=100/1023): + '''Read joystick''' + y_axis = 1023 - (self._rreg(_CC_G1_ADC) << 2 | self._rreg(_CC_G1_ADC + 1) >> 6) + x_axis = self._rreg(_CC_G1_ADC + 2 ) << 2 | self._rreg(_CC_G1_ADC + 3) >> 6 + return round(x_axis*ratio), round(y_axis*ratio) + + def read_key(self, index): + '''Read key1~6''' + if not 0 <= index <= 5: + raise ValueError("The key number must be a number in the range: 0~5") + if index<=4: + return bool(self._rreg(_CC_G1_KEY) >> index & 0x01) + else: + return bool(self._rreg(_CC_G1_KEY) >> 7 & 0x01) + + def shutdown(self, flag=True): + """This function is only available on battery power""" + if flag: + self._wreg(_CC_G1_KEY, (self._rreg(_CC_G1_KEY)) & 0XBF) + else: + self._wreg(_CC_G1_KEY, (self._rreg(_CC_G1_KEY)) | 0X40) + +'''Select instantiation objects''' +try: + #MixGo CC/ME + ext_i2c = SoftI2C(scl=Pin(0), sda=Pin(1), freq=100000) + handle = Handle(ext_i2c) +except: + try: + #MixGo CE + ext_i2c = SoftI2C(scl=Pin(17), sda=Pin(18), freq=100000) + handle = Handle(ext_i2c) + except: + try: + #MixGo Mini + ext_i2c = SoftI2C(scl=Pin(8), sda=Pin(7), freq=100000) + handle = Handle(ext_i2c) + except: + print("MixGo board cannot find a CC_G1") diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ch914x_at.py b/mixly/boards/default_src/micropython/origin/build/lib/ch914x_at.py new file mode 100644 index 00000000..218d6482 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ch914x_at.py @@ -0,0 +1,147 @@ +""" +Bluetooth AT + +Micropython library for the Bluetooth AT(WCH) +======================================================= + +#Preliminary composition 20230106 + +dahanzimin From the Mixly Team +""" +from machine import Pin +from time import sleep_ms + +class AT: + def __init__(self, pin,times=5): + self.at_pin = Pin(pin, Pin.OUT) + self.at_pin.value(1) + self._times = times + self._flag = [0,0,0,0,0,0,0,0] #mac0,1 name2,3 power4,5 power6,7 + self._power = [0,1,2,3,-3,-8,-14,-20] + sleep_ms(100) + + def _str_reverse(self,data): + data=data.split(':') + data.reverse() + data=":".join(data) + return data + + def ble_mac(self, mac=None): + sleep_ms(200) + if mac is None: + if not (self._flag[0] >= self._times and self._times != 0): + self._flag[0]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+MAC?\r\n') + input() + self.at_pin.value(1) + print('BLE_MAC:',self._str_reverse(data)) + sleep_ms(100) + return self._str_reverse(data) + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[1] >= self._times and self._times != 0): + self._flag[1]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+MAC={}\r\n'.format(self._str_reverse(mac))) + print('\r\n') + self.at_pin.value(1) + print('BLE_MAC:',mac,data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') + + def ble_name(self, name=None): + sleep_ms(200) + if name is None: + if not (self._flag[2] >= self._times and self._times != 0): + self._flag[2]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+NAME?\r\n') + input() + input() + self.at_pin.value(1) + print('BLE_NAME:',data) + sleep_ms(100) + return data + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[3] >= self._times and self._times != 0): + self._flag[3]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+NAME='+name+'\r\n') + print('\r\n') + self.at_pin.value(1) + print('BLE_NAME:',name,data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') + + def ble_power(self, power=None): + sleep_ms(200) + if power is None: + if not (self._flag[4] >= self._times and self._times != 0): + self._flag[4]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+TPL?\r\n') + input() + print(' \r\n') + self.at_pin.value(1) + data=self._power[int(data[4:])] + print('BLE_Power: {}DB'.format(data)) + sleep_ms(100) + return data + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[5] >= self._times and self._times != 0): + self._flag[5]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+TPL={}\r\n'.format(self._power.index(power))) + print('\r\n') + self.at_pin.value(1) + print('BLE_Power:',str(power)+'DB',data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') + + def ble_pname(self, name=None): + sleep_ms(200) + if name is None: + if not (self._flag[6] >= self._times and self._times != 0): + self._flag[6]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+PNAME?\r\n') + input() + input() + self.at_pin.value(1) + print('BLE_PNAME:',data) + sleep_ms(100) + return data + else: + print('Please delete this command and upload other programs again') + else: + if not (self._flag[7] >= self._times and self._times != 0): + self._flag[7]+=1 + self.at_pin.value(0) + sleep_ms(10) + data=input('AT+PNAME='+name+'\r\n') + print('\r\n') + self.at_pin.value(1) + print('BLE_PNAME:',name,data) + sleep_ms(100) + return True if data is "OK" else False + else: + print('Please delete this command and upload other programs again') diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ci130x.py b/mixly/boards/default_src/micropython/origin/build/lib/ci130x.py new file mode 100644 index 00000000..11152caa --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ci130x.py @@ -0,0 +1,129 @@ +""" +CI130X + +MicroPython library for the CI130X (ASR-I2C) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from struct import pack +from micropython import const + +_CI_ADDRESS = const(0x64) +_CI_ID_GET = const(0x02) +_CI_ID_SET = const(0x03) +_CI_ID_NUM = const(0x06) +_CI_ID_CLE = const(0x07) +_CI_ID_PACTRL = const(0x09) +_CI_ID_ASREN = const(0x0A) +_CI_ID_END = const(0x5A) +_TIME_SNUM = const(0x75) + +class CI130X: + def __init__(self, i2c_bus, addr=_CI_ADDRESS): + self._device = i2c_bus + self._address = addr + self._cmd_id = None + self._enable = True + try: + self._rreg(_CI_ID_GET, 3) + except: + try: #C130X 启动慢,加延时判断 + time.sleep_ms(850) + self._rreg(_CI_ID_GET, 3) + except: + raise AttributeError("Cannot find a CI130X") + + def _wreg(self, reg): + '''Write memory address''' + self._device.writeto(self._address, reg) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes) + + def status(self): + """返回 (是否唤醒, 是否播放)""" + _buf = self._rreg(_CI_ID_GET, 3) + return (bool(_buf[1] & 0x01), bool(_buf[1] & 0x10)) if _buf[2] == _CI_ID_END else (None, None) + + def cmd_id(self, repeat=False): + """返回 识别命令词对应ID""" + _buf = self._rreg(_CI_ID_GET, 3) + if not repeat: + self._wreg(bytes([_CI_ID_CLE, 0, 0, _CI_ID_END])) + time.sleep_ms(50) + self._cmd_id = _buf[0] if _buf[2] == _CI_ID_END else None + return self._cmd_id + + def result(self, ext_id=None): + """获取比较结果 或者输出结果""" + return self._cmd_id if ext_id is None else bool(self._cmd_id == ext_id) + + def sys_cmd(self, value, blocking=True): + """系统命令,1,2唤醒 202~205音量调整 206,207回复播报开关 208退出唤醒""" + self.play_id(value, blocking) + + def play_id(self, value, blocking=True): + """播放命令词对应ID语音""" + self._wreg(bytes([_CI_ID_SET, value, 0, _CI_ID_END])) + while blocking: + time.sleep_ms(15) + if not self.status()[1]: + break + + def play_num(self, value, blocking=True): + """播放浮点数据的合成语音""" + self._wreg(bytes([_CI_ID_NUM]) + pack('d', float(value)) + bytes([0, _CI_ID_END])) + while blocking: + time.sleep_ms(10) + if not self.status()[1]: + break + + def play(self, star=None, num=None, end=None, delay=10): + """组合播报名词+数值+单位""" + if star is not None: + self.play_id(star) + time.sleep_ms(delay) + if num is not None: + self.play_num(num) + time.sleep_ms(delay) + if end is not None: + self.play_id(end) + time.sleep_ms(delay) + + def play_time(self, times=None, detail=True, delay=10): + """播报时间""" + data = time.localtime() if times is None else times + if detail: + for i in range(0, 3): #年 月 日 + self.play_num(data[i]) + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + i) + time.sleep_ms(delay) + + for i in range(3, 5): #时 分 + self.play_num(data[i]) + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + i) + time.sleep_ms(delay) + + if detail: + self.play_num(data[5]) #秒 + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + 5) + time.sleep_ms(delay) + self.play_id(_TIME_SNUM + 6) #星期 + time.sleep_ms(delay) + self.play_num(data[6] + 1) + + def pa_ctrl(self, value=True, delay=10): + self._wreg(bytes([_CI_ID_PACTRL, int(value), 0, _CI_ID_END])) + if value: time.sleep_ms(delay) + + def asr_en(self, value=None): + if value is None: + return self._enable + else: + self._enable = bool(value) + self._wreg(bytes([_CI_ID_ASREN, self._enable, 0, _CI_ID_END])) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/debugnet.py b/mixly/boards/default_src/micropython/origin/build/lib/debugnet.py new file mode 100644 index 00000000..b2955ec9 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/debugnet.py @@ -0,0 +1,166 @@ +""" +Debugnet(HTTP,MQTT) + +MicroPython library for network request debugging +======================================================= + +#Preliminary composition 20230225 + +@dahanzimin From the Mixly Team +""" +import time +from umqtt import MQTTClient +from ubinascii import hexlify +from machine import unique_id +from urequests import Response +from usocket import socket,getaddrinfo,SOCK_STREAM +from mixiot import WILL_TOPIC,ADDITIONAL_TOPIC + +class socket_d(socket): + def __init__(self,*args,debug=False,**kw): + super().__init__(*args,**kw) + self._debug=debug + self.client_len=0 + self.server_len=0 + + def write(self,*args): + super().write(*args) + self.client_len=min(self.client_len+len(args[0]),65535) + if self._debug: + print('client:',args[0]) + + def readline(self,*args): + buf=super().readline(*args) + self.server_len=min(self.server_len+len(buf),65535) if buf else self.server_len + if self._debug: + print('server:',buf) + return buf + + def read(self,*args): + buf=super().read(*args) + self.server_len=min(self.server_len+len(buf),65535) if buf else self.server_len + if self._debug: + print('server:',buf) + return buf + +#HTTP +def request(method, url, data=None, json=None, headers={}, stream=None, parse_headers=True, debug=False): + redir_cnt = 1 + while True: + try: + proto, dummy, host, path = url.split("/", 3) + except ValueError: + proto, dummy, host = url.split("/", 2) + path = "" + if proto == "http:": + port = 80 + elif proto == "https:": + import ussl + port = 443 + else: + raise ValueError("Unsupported protocol: " + proto) + if ":" in host: + host, port = host.split(":", 1) + port = int(port) + ai = getaddrinfo(host, port, 0, SOCK_STREAM) + ai = ai[0] + resp_d = None + if parse_headers is not False: + resp_d = {} + s = socket_d(ai[0], ai[1], ai[2], debug=debug) + try: + s.connect(ai[-1]) + if proto == "https:": + s = ussl.wrap_socket(s, server_hostname=host) + s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) + if not "Host" in headers: + s.write(b"Host: %s\r\n" % host) + for k in headers: + s.write(k) + s.write(b": ") + s.write(headers[k]) + s.write(b"\r\n") + if json is not None: + assert data is None + import ujson + data = ujson.dumps(json) + s.write(b"Content-Type: application/json\r\n") + if data: + s.write(b"Content-Length: %d\r\n" % len(data)) + s.write(b"Connection: close\r\n\r\n") + if data: + s.write(data) + l = s.readline() + l = l.split(None, 2) + status = int(l[1]) + reason = "" + if len(l) > 2: + reason = l[2].rstrip() + while True: + l = s.readline() + if not l or l == b"\r\n": + break + if l.startswith(b"Transfer-Encoding:"): + if b"chunked" in l: + raise ValueError("Unsupported " + l) + elif l.startswith(b"Location:") and 300 <= status <= 399: + if not redir_cnt: + raise ValueError("Too many redirects") + redir_cnt -= 1 + url = l[9:].decode().strip() + status = 300 + break + if parse_headers is False: + pass + elif parse_headers is True: + l = l.decode() + k, v = l.split(":", 1) + resp_d[k] = v.strip() + else: + parse_headers(l, resp_d) + except OSError: + s.close() + raise + if status != 300: + break + resp = Response(s) + resp.status_code = status + resp.reason = reason + resp.client_len=s.client_len + resp.server_len=s.server_len + if resp_d is not None: + resp.headers = resp_d + return resp + +class MQTT_Client(MQTTClient): + def __init__(self,*args,debug=False,**kw): + super().__init__(*args,**kw) + self.sock = socket_d(debug=debug) + + @property + def client_len(self): #The length of client data obtained + _len=self.sock.client_len + self.sock.client_len=0 + return _len + + @property + def server_len(self): #The length of server data obtained + _len=self.sock.server_len + self.sock.server_len=0 + return _len + + def time_msg(self,utc=28800): #Get server time information + msg=self.wait_msg() + if isinstance(msg, dict): + if msg['topic'] =='$SYS/hello': + val=time.gmtime(int(msg['msg'])//1000-946684800+utc)[0:7] + return str(val).replace(' ','')[1:-1] + +#MQTT +def init_MQTT_client(address, username, password, MQTT_USR_PRJ, debug=False): + client = MQTT_Client(hexlify(unique_id()), address, 1883, username, password, debug=debug) + client.set_last_will(topic=MQTT_USR_PRJ+WILL_TOPIC, msg=client.client_id, qos=2) + if client.connect()==0: + client.publish(MQTT_USR_PRJ+ADDITIONAL_TOPIC, client.client_id, qos=0) + time.sleep_ms(200) + return client diff --git a/mixly/boards/default_src/micropython/origin/build/lib/dhtx.py b/mixly/boards/default_src/micropython/origin/build/lib/dhtx.py new file mode 100644 index 00000000..0755ad6f --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/dhtx.py @@ -0,0 +1,60 @@ +# DHT11/DHT22 driver for MicroPython +# MIT license; Copyright (c) 2016 Damien P. George + +from time import sleep +try: + from esp import dht_readinto +except: + from machine import dht_readinto +from machine import Pin + +class DHTBase: + __species = {} + __first_init = True + def __new__(cls, pin, *args, **kwargs): + if pin not in cls.__species.keys(): + cls.__first_init = True + cls.__species[pin] = object.__new__(cls) + return cls.__species[pin] + + def __init__(self, pin): + if self.__first_init: + self.__first_init = False + self.pin = Pin(pin) + self.buf = bytearray(5) + self.err = 0 + + def measure(self): + buf = bytearray(5) + try: + dht_readinto(self.pin, buf) + if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF == buf[4]: + self.buf = buf + self.err = 0 + except: + if self.err > 10: + raise AttributeError("DHTx operation error") + self.err += 1 + sleep(0.5) + return + +class DHT11(DHTBase): + def humidity(self): + self.measure() + return self.buf[0] + + def temperature(self): + self.measure() + return self.buf[2] + +class DHT22(DHTBase): + def humidity(self): + self.measure() + return (self.buf[0] << 8 | self.buf[1]) * 0.1 + + def temperature(self): + self.measure() + t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1 + if self.buf[2] & 0x80: + t = -t + return t diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ds18b20.py b/mixly/boards/default_src/micropython/origin/build/lib/ds18b20.py new file mode 100644 index 00000000..fae95bc5 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ds18b20.py @@ -0,0 +1,67 @@ +# DS18x20 temperature sensor driver for MicroPython. +# MIT license; Copyright (c) 2016 Damien P. George + +import onewire +from machine import Pin +from micropython import const + +_CONVERT = const(0x44) +_RD_SCRATCH = const(0xBE) +_WR_SCRATCH = const(0x4E) + +class DS18X20: + __species = {} + __first_init = True + def __new__(cls, pin, *args, **kwargs): + if pin not in cls.__species.keys(): + cls.__first_init = True + cls.__species[pin] = object.__new__(cls) + return cls.__species[pin] + + def __init__(self, pin): + if self.__first_init: + self.__first_init = False + self._ow = onewire.OneWire(Pin(pin, pull=Pin.PULL_UP)) + self._buf = bytearray(9) + self._roms = self.scan() + if len(self._roms) == 0: + raise AttributeError("Cannot find a DS18X20") + + def scan(self): + return [rom for rom in self._ow.scan() if rom[0] in (0x10, 0x22, 0x28)] + + def convert_temp(self): + self._ow.reset(True) + self._ow.writebyte(self._ow.SKIP_ROM) + self._ow.writebyte(_CONVERT) + + def read_scratch(self, rom): + self._ow.reset(True) + self._ow.select_rom(rom) + self._ow.writebyte(_RD_SCRATCH) + self._ow.readinto(self._buf) + if self._ow.crc8(self._buf): + raise Exception("CRC error") + return self._buf + + def read_temp(self, rom): + buf = self.read_scratch(rom) + if rom[0] == 0x10: + if buf[1]: + t = buf[0] >> 1 | 0x80 + t = -((~t + 1) & 0xFF) + else: + t = buf[0] >> 1 + return t - 0.25 + (buf[7] - buf[6]) / buf[7] + else: + t = buf[1] << 8 | buf[0] + if t & 0x8000: # sign bit set + t = -((t ^ 0xFFFF) + 1) + return t / 16 + + def temperature(self): + temp = [] + self.convert_temp() + for rom in self._roms: + temp.append(round(self.read_temp(rom), 2)) + return temp [0] if len(temp) == 1 else tuple(temp) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/expression_picture.py b/mixly/boards/default_src/micropython/origin/build/lib/expression_picture.py new file mode 100644 index 00000000..a0cab8ba --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/expression_picture.py @@ -0,0 +1,21 @@ +#Take the picture bytes in expression_picture.py +#--dahanzimin From the Mixly Team + +Angry=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x01\x87\xfc\x00\x00\x7f\x80\x00\x01\xd9\xfe\x00\x00\xff\x00\x00\x07\xfc\xff\x00\x01\xfe\x00\x00\x07\xfe\x7f\x80\x01\xfc\x00\x00\x03\x1c?\x80\x03\xf8\x00\x00\x0f\x18\x1f\xc0\x03\xf0\x00\x00\x0e\xdc\x0f\xc0\x07\xf0\x00\x00\x07\xfc\x0f\xe0\x07\xe0\x00\x00\x07\xf8\x07\xe0\x0f\xc0\x00\x00\x02`\x03\xf0\x0f\xc0\x00\x00\x00 \x03\xf0\x1f\xc0\x00\x00\x00\x00\x03\xf8\x1f\x83\x00\x00\x00\x00\xc1\xf8\x1f\x83\xc0\x00\x00\x03\xc1\xf8\x1f\x03\xf0\x00\x00\x1f\xc1\xf8?\x07\xfe\x00\x00?\xe0\xfc?\x03\xff\x80\x01\xff\xc0\xfc?\x03\xff\xe0\x07\xff\xc0\xfc?\x03\xff\xe0\x03\xff\x80\xfc?\x01\xff\xc0\x03\xff\x80|?\x00\xff\x80\x01\xff\x00\xfc>\x00>\x00\x00|\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xc0\x00\x00\x00\x00\x07\xf0\x07\xe0\x00\x03\x80\x00\x07\xe0\x07\xf0\x00\x07\xc0\x00\x0f\xe0\x03\xf0\x00\x0f\xf0\x00\x0f\xc0\x03\xf8\x00\x1e\xf8\x00\x1f\xc0\x01\xfc\x00\x1c~\x00?\x80\x01\xfe\x00\x00\x1c\x00\x7f\x80\x00\xff\x00\x00\x04\x00\xff\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x05\xff\xe0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Bored=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x0f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\x80\x00\x00\x00\x00\x03\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x83[\x00\x00\xdfA\xf8\x1f\x87\xff\x80\x01\xff\xe0\xf8?\x07\xff\x00\x01\xff\xe0\xfc?\x01}\x00\x00\x8e\x00\xfc?\x000\x00\x00\x0e\x00\xfc?\x00p\x00\x00\x1c\x00\xfc>\x05~\x80\x00_\xc0|?\x07\xff\x80\x01\xff\xe0\xfc?\x07\xff\x80\x01\xff\xe0\xfc>\x02D\x00\x00\xa4\x80|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x07\xf0\x00\x03\xf0\x0f\xe0\x00\x1f\xfc\x00\x07\xf0\x07\xe0\x00?\xfe\x00\x07\xe0\x07\xf0\x00|\x1f\x00\x07\xe0\x03\xf8\x00p\x07\x00\x1f\xc0\x03\xf8\x00\xe0\x07\x80\x1f\xc0\x01\xfc\x00s\xe3\x80?\x80\x00\xfe\x00c\xf3\x00\x7f\x00\x00\xff\x00\x03\xe0\x00\xff\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xfa\xbf\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfe\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x00_\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Confused=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x06\x00\x00\x00\x1f\xc0\x03\xf0\x0f\x00\x01\xfc\x1f\xc0\x07\xf0\x1f\x00\x01\xff\x0f\xe0\x07\xe0?\x00\x01\xff\x87\xe0\x0f\xc0~\x00\x00\xff\xc7\xf0\x0f\xdf\xfc\x00\x00\x07\xe3\xf0\x1f\xdf\xf8\x00\x00\x01\xf3\xf8\x1f\x9f\xe0\x00\x00\x00\xf1\xf8\x1f\x8f(\x00\x00\x18\xe1\xf8\x1f\x00~\x00\x00~!\xf8?\x00\xff\x00\x00\xfe\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00~\x00\x00\xfe\x00\xfc>\x00>\x00\x00|\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xf8?\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xe0\x00\x00\x00\x00\x03\xf0\x07\xe0\x00\x00\x00\x00\x07\xe0\x07\xf0\x00\x1f\x80\x00\x0f\xe0\x03\xf0\x00?\xc0\x00\x0f\xc0\x03\xf8\x00?\xc7\x00\x1f\xc0\x01\xfc\x009\xe7\x00?\x80\x00\xfe\x001\xe7\x00\x7f\x80\x00\xff\x000\xfe\x00\xff\x00\x00\x7f\xc0\x00~\x03\xfe\x00\x00?\xe0\x00<\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xfe\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x01\xff\xff\x80\x00\x00\x00\x00\x00?\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Happy=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xff\x7f\xff\xc0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfe\x00\x00\x00\x00\x7f\x00\x03\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf8\x00\x00\x00\x00\x0f\xc0\x07\xe0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\xc0\x00\x00\x00\x00\x03\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x14\x00\x008\x01\xf8\x1f\x00~\x00\x00~\x00\xf8?\x00\xff\x00\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00\xff\x00\x00\xff\x00\xfc?\x00\x7f\x00\x00\xfe\x00|>\x00<\x00\x00|\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xf8?\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xe0\x02\xfa\xd5\x80\x07\xf0\x07\xe0\x03\xff\xff\xc0\x07\xe0\x07\xf0\x07\xff\xff\xe0\x0f\xe0\x03\xf8\x03\xff\xff\xc0\x0f\xc0\x03\xf8\x03\xff\xff\xc0\x1f\xc0\x01\xfc\x01\xff\xff\x80?\x80\x01\xfe\x01\xff\xff\x80\x7f\x80\x00\xff\x00\xff\xff\x00\xff\x00\x00\x7f\x80\x7f\xfe\x03\xfe\x00\x00?\xe0?\xfc\x07\xfc\x00\x00\x1f\xf0\x07\xf0\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xfe\xbf\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Heart=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfe\x00\x00\x7f\xc0\x00\x00\x1f\xff\xc0\x03\xff\xf8\x00\x00\x7f\xff\xf0\x0f\xff\xfe\x00\x00\xff\xff\xf8\x1f\xff\xff\x00\x01\xff\xff\xfe\x7f\xff\xff\x80\x03\xff\xff\xff\x7f\xff\xff\xc0\x07\xff\xff\xff\xff\xff\xff\xe0\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xfc\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xc0\x01\xff\xff\xff\xff\xff\xff\x80\x00\xff\xff\xff\xff\xff\xff\x80\x00\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xff\xff\xff\xfe\x00\x00?\xff\xff\xff\xff\xfc\x00\x00\x1f\xff\xff\xff\xff\xf8\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x01\xff\xff\xff\xff\xc0\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xfe\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x1f\xff\xff\xf8\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xff\x80\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x00?\xfe\x00\x00\x00\x00\x00\x00\x1f\xf8\x00\x00\x00\x00\x00\x00\x0f\xf0\x00\x00\x00\x00\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Paper=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x00\x00\x00\x00\x01\xff\x00`\x00\x00\x00\x00\x01\xff\x83\xfc\x00\x00\x00\x00\x07\xff\xc7\xff\x00\x00\x00\x00\x07\xe7\xcf\xff\x80\x00\x00\x00\x0f\x83\xff\xff\x80\x00\x00\x00\x0f\x03\xff\x07\x80\x00\x00\x00\x0f\x03\xfe\x07\xc0\x00\x00\x00\x1f\x01\xfc\x03\xc0\x00\x00\x00\x1e\x01\xf8\x03\xc0\x00\x00\x00\x1e\x01\xf8\x07\xcc\x00\x00\x00\x1e\x03\xf0\x07\xff\x00\x00\x00\x1e\x03\xe0\x0f\xff\x80\x00\xbc\x1e\x03\xe0\x0f\xff\xc0\x01\xff\x1e\x03\xc0\x1f\xff\xc0\x03\xff\xfe\x03\xc0?\xc3\xe0\x07\xff\xfe\x01\xc0?\x81\xe0\x07\xc7\xfe\x00\x00~\x01\xe0\x07\x81\xfe\x00\x00\xfc\x01\xe0\x0f\x80\xfe\x00\x01\xf8\x03\xe0\x0f\x80~\x00\x01\xf0\x07\xc0\x07\x80>\x00\x00\xe0\x0f\xc0\x07\x80\x1e\x00\x00@\x1f\x80\x07\xc0\x0e\x00\x00\x00?\x00\x03\xe0\x06\x00\x00\x00~\x00\x03\xe0\x06\x00\x00\x00\xfc\x00\x01\xf0\x02\x00\x00\x03\xff\x00\x00\xf8\x00\x00\x00\x07\xff\xc0\x00\xfc\x00\x00\x00\x07\xff\xe0\x00|\x00\x00\x00\x07\xff\xe0\x00>\x00\x00\x00\x03\x81\xf0\x00\x1e\x00\x00\x00\x00\x00\xf0\x00\x1e\x00\x00\x00\x00\x00\xf0\x00\x1e\x00\x00\x00\x00\x01\xf0\x00\x1e\x00\x00\x00\x00\x03\xf0\x00\x1e\x00\x00\x00\x00\x07\xe0\x00>\x00\x00\x00\x00\x7f\xc0\x00<\x00\x00\x00\xff\xff\x80\x00|\x00\x00\x01\xff\xff\x00\x00|\x00\x00\x03\xff\xfc\x00\x00<\x00\x00\x03\xff\xe0\x00\x00<\x00\x00\x07\xe0\x00\x00\x00>\x00\x00\x0f\x80\x00\x00\x00>\x00\x00\x1f\x80\x00\x00\x00\x1f\x00\x00?\x00\x00\x00\x00\x0f\x80\x00~\x00\x00\x00\x00\x0f\xc0\x00\xfc\x00\x00\x00\x00\x07\xf0\x03\xf8\x00\x00\x00\x00\x03\xf8\x07\xf0\x00\x00\x00\x00\x01\xff?\xc0\x00\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Rock=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\xc1\xff\xc0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x1f\xff\xff\xf0\x00\x00\x00\x00?\xff\xc3\xf8\x00\x00\x00\x00?\xff\x00\xff\xf0\x00\x00\x00|\x0f\x00\x7f\xfc\x00\x00\x00x\x0e\x00\xff\xfe\x00\x00\x07\xf8\x1e\x03\xff\xff\x00\x00\x1f\xf8\x1c\x0f\xf0\x1f\x80\x00?\xf0\x1c\x1f\x80\x0f\xc0\x00\x7f\xf0\x1c\x1e\x00\x07\xe0\x00\xfe\xf0\x1e<\x00\x03\xe0\x00\xf8p\x1e8\x00\x01\xe0\x00\xf0p\x0e8\x00\x01\xf0\x01\xf0x\x0e8\x00\x00\xf0\x01\xe0x\x0f8\x00\x00\xf0\x01\xe0<\x078\x00\x00\xf0\x01\xe0<\x07\xfc\x0f\x00\xf0\x03\xe0\x1e\x03\xbf\xff\x00\xf0\x0f\xf0\x1f\x03\xff\xff\x00\xf8\x1f\xf0\x0f\x81\xef\xfc\x00\xf8\x1f\xf0\x07\xc0\xff\xe0\x00x>x\x03\xe0\xff\x80\x00\xf8><\x01\xf1\xfc\x00\x00\xf8<>\x00\xff\xf0\x00\x00\xf8<\x1f\x00\x7f\xc0\x00\x00\xf0<\x0f\x80?\x00\x00\x00\xf0>\x07\xc0~\x00\x00\x00\xf0\x1e\x03\xe1\xf8\x00\x00\x00\xf0\x1f\x01\xf3\xf0\x00\x00\x01\xf0\x1f\x00\xff\xc0\x00\x00\x01\xe0\x0f\x80\x7f\x80\x00\x00\x01\xe0\x0f\x80\x1f\x00\x00\x00\x03\xe0\x07\xc0\x1e\x00\x00\x00\x03\xe0\x03\xe0<\x00\x00\x00\x07\xc0\x03\xf8x\x00\x00\x00\x0f\xc0\x01\xfcx\x00\x00\x00\x1f\x80\x00\xff\xf0\x00\x00\x00\x7f\x00\x00?\xf0\x00\x00\x01\xfe\x00\x00\x1f\xf0\x00\x00\x07\xfc\x00\x00\x07\xf0\x00\x00\x1f\xf0\x00\x00\x00\xf8\x00\x00?\xc0\x00\x00\x00|\x00\x00\xff\x80\x00\x00\x00~\x00\x03\xfe\x00\x00\x00\x00?\x00\x0f\xf8\x00\x00\x00\x00\x1f\x80?\xe0\x00\x00\x00\x00\x1f\xe0\xff\x80\x00\x00\x00\x00\x07\xff\xfe\x00\x00\x00\x00\x00\x03\xff\xf8\x00\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x00\x00\x7f\xc0\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Sad=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfe\xff\xff\xc0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x1f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x0f\xe0\x00\x00\x00\x00\x07\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\xc0\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8?\x00\x00\x00\x00\x00\x01\xfc\x1f\x07\xff\xe0\x0f\xff\xc0\xf8?\x07\xff\xe0\x0f\xff\xe0\xfc?\x07\xff\xf0\x0f\xff\xc0\xfc?\x07\xff\xe0\x0f\xff\xc0\xfc?\x00\x7f\x00\x00\xfe\x00\xfc?\x00?\x00\x00\xfc\x00\xfc>\x00\x7f\x00\x00\xfe\x00|?\x00?\x00\x00~\x00\xfc?\x00~\x00\x00\xfe\x00\xfc?\x00?\x00\x00\xfe\x00\xfc?\x00\x7f\x00\x00\xfc\x00\xfc\x1f\x00\x7f\x00\x00\xfe\x00\xf8\x1f\x00?\x00\x00\xfe\x01\xfc\x1f\x80\x7f\x00\x00\xfe\x01\xf8\x1f\x80\x7f\x00\x00\xfe\x01\xf8\x1f\xc0?\x00\x00|\x01\xf8\x0f\xc0\x7f\x00\x00\xfe\x03\xf0\x0f\xe0\x7f\x0f\xe0\xfe\x03\xf0\x07\xe0?\x1f\xf8\xfe\x07\xe0\x07\xf0\x7f\x7f\xfe\xfc\x0f\xe0\x03\xf0\x7f|?~\x0f\xc0\x03\xf8?\xf0\x0f\xfe\x1f\xc0\x01\xfc\x7f\xe0\x07\xfe?\x80\x00\xfe\x7f\xc0\x03\xfe\x7f\x00\x00\xff?@\x02\xfe\xff\x00\x00\x7f\xff\x00\x00\xff\xfe\x00\x00?\xff\x00\x00\xff\xfc\x00\x00\x1f\xff\x00\x00\xff\xf8\x00\x00\x0f\xff\x00\x00\xff\xf0\x00\x00\x07\xff\xc0\x00\xff\xe0\x00\x00\x01\xff\xff\x7f\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Scissors=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x00\x00\x00\x00\x00?\xf0\x00\x00\x00\x00\x00\x00\xff\xfc\x00\x00\x00\x00\x00\x01\xff\xff\x00\x00\x00\x00\x00\x01\xf8\xff\x80\x00\x00\x00\x00\x03\xe0\x1f\xc0\x00\x00\x00\x00\x07\xc0\x07\xf0\x00\x00\x00\x00\x07\xc0\x03\xf8\x00\x00\x00\x00\x07\x80\x01\xfc\x00\x00\x00\x00\x07\x80\x00~\x00\x00\x00\x00\x07\x80\x00?\x00\x00\x00\x00\x07\x80\x00\x1f\xfc\x00\x00\x00\x07\xc0\x00\x0f\xff\x80\x00\x00\x03\xe0\x00\x07\xff\xe0\x00\x00\x03\xf0\x00\x03\xff\xf8\x00\x00\x01\xf8\x00\x00\xe7\xfc\x00\x00\x00\xfc\x00\x01\xe0\xfe\x00\x00\x00\x7f\x00\x01\xe0?\x00\x00\x03\xff\x80\x01\xc0\x1f\x80\x00\x7f\xff\xe0\x03\xc0\x1f\x80\x01\xff\xff\xf8\x03\x80\x1f\xc0\x03\xff\xff\xff\x03\x80\x1f\xe0\x07\xff\xff\xff\x07\x80\x1f\xe0\x0f\xc0\x01\xff\x07\x00\x1f\xe0\x0f\x80\x00\x1e\x07\x00=\xf0\x1f\x00\x00\x00\x07\x00<\xf0\x1e\x00\x00\x00\x07\x008\xf0\x1e\x00\x00\x00\x0f\x00x\xf0\x1e\x00\x00\x00\x7f\x00\xf0\xf0\x1f\x00\x00\x01\xff\x00\xf0\xf8\x0f\x00\x00\x07\xff\x01\xe0\xf8\x0f\x80\x00\x0f\xef\x03\xc0x\x0f\xe0\x00?\x07\x87\xc0\xf8\x07\xff\x7f\xfe\x03\xff\x80\xf8\x03\xff\xff\xfc\x03\xff\x00\xf8\x01\xff\xff\xf8\x01\xfe\x00\xf0\x00\x7f\xff\xf8\x07\xff\x00\xf0\x00\x01\xd0|\x7f\xff\xc0\xf0\x00\x00\x00\x7f\xff\xff\xe0\xf0\x00\x00\x00?\xfc\x01\xf1\xf0\x00\x00\x00\x1f\xe0\x00\xf1\xe0\x00\x00\x00\x0f\x00\x00s\xe0\x00\x00\x00\x0f\x00\x00s\xe0\x00\x00\x00\x0f\x00\x00\xff\xc0\x00\x00\x00\x0f\x00\x00\xff\x80\x00\x00\x00\x0f\x80\x03\xff\x00\x00\x00\x00\x07\xf0\xff\xfe\x00\x00\x00\x00\x07\xff\xff\xfc\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xfe\x00\x00\x00\x00\x00\x007@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Silly=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xf4\x1f\xff\xc0\x00\x00\x07\xff\x00\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x1f\xf0\x00\x00\x0f\xf8\x00\x00?\xc0\x00\x00\x03\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfc\x00\x00\x00\x00?\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x07\xf0\x01\x00\x00\x00\x0f\xc0\x07\xe0\x03\x80\x01\xe0\x07\xe0\x07\xe0\x07\x80\x01\xe0\x07\xe0\x0f\xc0\x0f\x80\x01\xf0\x03\xf0\x0f\xc0?\x00\x00\xfc\x03\xf0\x1f\x87\xfe\x00\x00\x7f\xe1\xf8\x1f\x87\xfc\x00\x00?\xe1\xf8\x1f\x07\xf8\x00\x00\x0f\xf0\xf8\x1f\x07\xcc\x00\x00s\xe1\xf8?\x00\x1f\x00\x00\xf8\x00\xfc?\x00?\x80\x01\xfc\x00\xfc?\x00\x7f\xc0\x03\xfc\x00|>\x00\x7f\xc0\x01\xfe\x00\xfc>\x00?\x80\x03\xfe\x00|>\x00?\x80\x01\xfc\x00|?\x00?\x80\x00\xf8\x00|>\x00\x0e\x00\x00p\x00\xfc>\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x03\xc0\x00\x00\xf8?\x00\x00\x07\xe0\x00\x00\xfc\x1f\x00\x00\x0f\xe0\x00\x00\xf8\x1f\x80\x00\x07\xe0\x00\x01\xf8\x1f\x80\x00\x07\xf0\x00\x01\xf8\x0f\xc0\x00\x0f\xe0\x00\x03\xf0\x0f\xc0\x00\x0f\xe0\x00\x03\xf0\x07\xe0\x00\x07\xe0\x00\x07\xe0\x07\xe0\x00\x07\xf0\x00\x07\xe0\x07\xf0\x00\x0f\xe0\x00\x0f\xc0\x03\xf8\x00\x07\xe0\x00\x1f\xc0\x01\xfc\x00\x0f\xf0\x00?\x80\x00\xfc\x00\x07\xe0\x00?\x00\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\x80\x07\xc0\x01\xfe\x00\x00?\xc0\x00\x80\x03\xfc\x00\x00\x1f\xf0\x00\x00\x0f\xf8\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x07\xff\x00\x01\xff\xe0\x00\x00\x01\xff\xfa7\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Sleep=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x03\xff\xc0\x03\xf0\x00\x00\x00\x07\xef\xc0\x07\xf0\x00\x00\x00\x00\xef\xe0\x07\xe0\x00\x00\x00\x01\xc7\xe0\x0f\xe0\x00\x00\x00\x07\xa7\xf0\x0f\xc0\x00\x00\x00\x07\xe3\xf0\x1f\x80\x00\x00\x00\xf3C\xf8\x1f\x80\x00\x00\x01\xf8\x01\xf8\x1f\x80\x00\x00\x00p\x01\xf8\x1f\x80\x00\x00\x00\xe0\x00\xf8?\x00\x00\x00\x01\xf8\x00\xfc?\x00\x00\x00\x00\xf0\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc>\x03\xff\xe0\x07\xaf\xc0\xfc?\x03\xff\xe0\x07\xff\xc0\xfc?\x03\xff\xe0\x07\xff\xc0|?\x01\xff\x80\x03\xff\x80\xfc>\x00\x00\x00\x00\x10\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x80\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x01@\x00\x01\xf8\x1f\xc0\x00\x1f\xf8\x00\x03\xf8\x0f\xc0\x00\x7f\xfe\x00\x03\xf0\x0f\xe0\x00\xff\xff\x00\x03\xf0\x07\xe0\x01\xff\xff\x80\x07\xe0\x07\xf0\x01\xff\xff\x80\x0f\xe0\x03\xf0\x03\xff\xff\xc0\x0f\xc0\x03\xf8\x03\xff\xff\xc0?\xc0\x01\xfc\x01\xff\xff\x80?\x80\x00\xfe\x01\xff\xff\x80\x7f\x80\x00\xff\x00|\x00\x00\xff\x00\x00\x7f\x80x\x00\x01\xfe\x00\x00?\xe0<\x00\x07\xfc\x00\x00\x1f\xf88\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x03\xff\xfd\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Small_heart=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\xe0\x07\xf8\x00\x00\x00\x00\x7f\xf8\x1f\xfe\x00\x00\x00\x00\xff\xfe?\xff\x00\x00\x00\x01\xff\xff\x7f\xff\x80\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x1f\xff\xff\xf8\x00\x00\x00\x00\x0f\xff\xff\xe0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xff\x00\x00\x00\x00\x00\x00\x7f\xff\x00\x00\x00\x00\x00\x00\x7f\xfc\x00\x00\x00\x00\x00\x00\x1f\xf8\x00\x00\x00\x00\x00\x00\x0f\xf8\x00\x00\x00\x00\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Small_paper=b'P4\n32\n32\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x1f\x1e\x00\x00;\xbf\x00\x001\xf3\x00\x00q\xe1\x80\x00a\xc3\xa0\x00a\x83\xf0\x1fa\x87\xf8?\xe1\x87\x181\xe0\x0e\x180\xe0\x1c80`\x08p\x18 \x00\xe0\x1c\x00\x01\xf0\x0e\x00\x03\xf8\x06\x00\x01\x1c\x06\x00\x00\x0c\x06\x00\x00\x1c\x06\x00\x00\xf8\x0e\x00\x1f\xf0\x06\x00\x1f\x80\x06\x000\x00\x07\x00p\x00\x03\x80\xe0\x00\x01\xc3\xc0\x00\x00\xff\x00\x00\x00>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Small_rock=b'P4\n32\n32\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00?\xf8\x00\x00\x7f\x9c\x00\x00\xe3\x0f\xe0\x03\xc6\x1f\xf0\x07\xc6p8\x0e\xc6`\x18\x0c\xc2@\x1c\x18\xc3@\x0c\x18c\xe3\x0c\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf0\x0f\xc0\x0e\x00\x000\x03\xf8\x0f\xe0\x0f\x00\x00x\x07\xe0\x07\xe0\x1f\x00\x00\xf0\x07\xf0\x07\xf0\x0f\x00\x00\xf0\x0f\xe0\x03\xf0\x07\x80\x01\xf0\x0f\xc0\x03\xf8\x07\xc0\x03\xe0\x1f\xc0\x01\xfc\x07\xe0\x07\xe0?\x80\x01\xfe\x03\xfc\x1f\xc0\x7f\x80\x00\xff\x01\xff\xff\x80\xff\x00\x00\x7f\xc0\xff\xfe\x03\xfe\x00\x00?\xe0?\xfc\x07\xfc\x00\x00\x1f\xf0\x0f\xf0\x1f\xf8\x00\x00\x0f\xfe\x00\x00?\xf0\x00\x00\x07\xff\xc0\x03\xff\xe0\x00\x00\x03\xff\xff\x7f\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Surprise=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x1f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x10\x00\x00\x10\x03\xf0\x1f\xc0>\x00\x00|\x01\xf8\x1f\x80\x7f\x00\x00~\x01\xf8\x1f\x80\xff\x00\x00\xff\x01\xf8\x1f\x80\xff\x80\x01\xff\x00\xf8?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc>\x00\x7f\x00\x00\xff\x00\xfc?\x00~\x00\x00~\x00|?\x00>\x00\x008\x00\xfc>\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x03\xc0\x00\x01\xf8\x1f\x80\x00\x07\xe0\x00\x01\xf8\x1f\xc0\x00\x0f\xf0\x00\x01\xf8\x0f\xc0\x00\x0f\xf0\x00\x03\xf0\x0f\xe0\x00\x0f\xf0\x00\x07\xf0\x07\xe0\x00\x0f\xf8\x00\x07\xe0\x07\xf0\x00\x1f\xf0\x00\x0f\xe0\x03\xf8\x00\x0f\xf8\x00\x0f\xc0\x03\xf8\x00\x0f\xf0\x00\x1f\xc0\x01\xfc\x00\x0f\xf0\x00?\x80\x00\xfe\x00\x0f\xe0\x00\x7f\x80\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\xc0\x03\xc0\x03\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00/\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Wonderful=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x02\x00\xff\xff\xff\xff\x00\x00\x07\x03\xff\xff\x7f\xff\xc0\x00\x07\x87\xff\x80\x03\xff\xe0\x00\x1f\xcf\xfc\x00\x00\x7f\xf0\x00\x1f\xdf\xf8\x00\x00\x1f\xf8\x00\x07?\xe0\x00\x00\x07\xfc\x00\x02\x7f\x80\x00\x00\x19\xfe\x00\x02\xff\x00\x00\x00\x1c\xff\x00\x00\xfe\x00\x00\x00>\x7f\x00\x01\xfc\x00\x00\x00\x7f?\x80\x03\xf8\x00\x00\x00\x1c\x1f\xc0\x03\xf0\x00\x00\x00\x18\x1f\xe0\x07\xf0\x00\x00\x00\x08\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xe0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0<\x00\x008\x03\xf0\x1f\x80\xff\x00\x00\xff\x01\xf8\x1f\x80\xff\x80\x01\xff\x01\xf8\x1f\x81\xff\x80\x01\xff\x81\xf8?\x83\xff\xc0\x01\xff\xc0\xfc\x1f\x01\xff\xc0\x03\xff\x80\xf8?\x03\xff\xc0\x03\xff\xc0\xfc?\x01\xff\xc0\x03\xff\x80\xfc?\x01\xff\x80\x01\xff\x80\xfc>\x00\xff\x80\x01\xff\x80|?\x00~\x00\x00\xfe\x00\xfc?\x00\x1c\x00\x008\x00\xfc>\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x01\x03\xf0\x0f\xc0\x00\x00\x00\x01\x83\xf8\x0f\xe0\x00\xff\xff\x03\xc3\xf0\x07\xe0\x00\xff\xff\x0f\xe7\xe0\x07\xf0\x00\xff\xff\x07\xcf\xe0\x03\xf0\x00\x7f\xff\x01\x9f\xc0\x03\xf8\x00\x7f\xfe\x01\x9f\xc0\x01\xfc\x00?\xfc\x00?\x80\x00\xfe\x00\x1f\xf8\x00\x7f\x80\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' diff --git a/mixly/boards/default_src/micropython/origin/build/lib/eye_picture.py b/mixly/boards/default_src/micropython/origin/build/lib/eye_picture.py new file mode 100644 index 00000000..0ab20db6 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/eye_picture.py @@ -0,0 +1,31 @@ +#Take the picture bytes in eye_picture.py +#--dahanzimin From the Mixly Team + +Eyes_Angry=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1e\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\x80\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\xe0\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1d\xf8\x00\x00\x07\x000\x00\x00\x00|\x7f\x1c\xfe\x00\x00\x07\x000\x00\x00\x01\xfc\x7f\x1c?\x80\x00\x07\x000\x00\x00\x07\xfc\x7f\x1c\x0f\xe0\x00\x07\x000\x00\x00\x1f\x8c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x00~\x0c\x7f\x1c\x00\xfe\x00\x07\x000\x00\x01\xf8\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x0f\xe0\x07\x000\x00\x1f\x80\x0c\x7f\x1c\x00\x07\xf8\x07\x000\x00\x7f\x00\x0c\x7f\x1c\x00\x0f\xfe\x07\x000\x01\xfc\x00\x0c\x7f\x1c\x00\x1f\xff\x87\x000\x07\xf6\x80\x0c\x7f\x1c\x00?\x9f\xe7\x000\x1f\xf2\x00\x0c\x7f\x1c\x00\xbf\xbb\xff\x000\x7f\xef\x00\x0c\x7f\x1c\x00\x7f\xfc\xff\x001\xff\xff@\x0c\x7f\x1c\x00\x7f\xfc?\x00?\xff\xff\x00\x0c\x7f\x1c\x00\x7f\xfc\x0f\x00?\xaf\xff@\x0c\x7f\x1c\x00?\xf8\x07\x00>\x0f\xff\x00\x0c\x7f\x1c\x00\xbf\xfa\x07\x008\x07\xfe\x00\x1c\x7f\x0e\x00\x1f\xf0\x0e\x008\x17\xfe\x80\x1c\x7f\x0e\x00\x0f\xe0\x0e\x00<\x03\xfc\x00<\x7f\x0f\x00\x03\x80\x1e\x00\x1c\x04\xf2\x008\x7f\x07\x80\x04 <\x00\x1e\x01\x08\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Awake=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\x00\x00\x00\x07\x000\x00\x00\x00|\x7f\x1f\xf8\x00\x00\x07\x000\x00\x00\x07\xfc\x7f\x1f\xff\xc0\x00\x07\x000\x00\x01\xff\xfc\x7f\x1c\x1f\xff\x00\x07\x000\x00?\xfe\x0c\x7f\x1c\x00\xff\xf0\x07\x000\x07\xff\xc0\x0c\x7f\x1c\x00?\xff\x87\x000\x7f\xfe\x00\x0c\x7f\x1c\x01\x7f\xff\xff\x00?\xff\xff\x00\x0c\x7f\x1c\x00~i\xff\x00?\xe1\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x0f\x00<\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\xff\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x01\x7f\xd0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00~\x00\x0c\x7f\x1c\x00@@\x07\x000\x00\x81\x00\x0c\x7f\x1c\x00\n\x00\x07\x000\x00(\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Black_eye=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00?\xff\xfc\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xff\xff\xff\x80\x7f\x00\x00\x00\x00\x00\x00\x03\xff\xff\xff\xc0\x7f\x00\x1f\xff\xfe\x00\x00\x07\xc0\x00\x03\xe0\x7f\x00\x7f\xff\xff\xc0\x00\x0f\x00\x00\x00\xf0\x7f\x01\xff\xff\xff\xf0\x00\x1e\x00\x00\x00x\x7f\x03\xfa\xaa\xab\xf8\x00\x1c\x00\x00\x008\x7f\x07\xd2U%|\x008\x00\x00\x00\x1c\x7f\x07\xad\xaa\xda\xbc\x008\x00\x00\x00\x1c\x7f\x0fRU%^\x008\x00\x00\x00\x1c\x7f\x0fm\xaa\xda\xae\x000\x00\x00\x00\x0c\x7f\x1e\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1dm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1e\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1dm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1c\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1fm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1c\x92U$\x97\x000\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00B\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x018\x80\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00\x7f\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x00\xfe`\x07\x000\x01\xfc\x80\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x01\xff\x80\x0c\x7f\x1f\xff\xff\xff\xff\x000\x05\xff\xa0\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00\xff\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x01<\x80\x0c\x7f\x1dUUUW\x000\x00B\x00\x0c\x7f\x1dT\x92UW\x000\x00\x00\x00\x0c\x7f\x1e\xabm\xaa\xaf\x000\x00\x00\x00\x0c\x7f\x1dT\x92UW\x000\x00\x00\x00\x0c\x7f\x1fKm\xaa\xaf\x000\x00\x00\x00\x0c\x7f\x0e\xb4\x92U\xae\x000\x00\x00\x00\x0c\x7f\x0fKm\xaa^\x008\x00\x00\x00\x1c\x7f\x07\xb4\x92U\xbc\x008\x00\x00\x00\x1c\x7f\x07\xcbm\xaa|\x00<\x00\x00\x00<\x7f\x03\xf4\x92K\xf8\x00\x1c\x00\x00\x008\x7f\x01\xff\xff\xff\xf0\x00\x1e\x00\x00\x00x\x7f\x00\x7f\xff\xff\xc0\x00\x0f\x80\x00\x01\xf0\x7f\x00\x1f\xff\xff\x00\x00\x07\xe0\x00\x07\xe0\x7f\x00\x00\x00\x00\x00\x00\x03\xff\xff\xff\xc0\x7f\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bottom_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\x80\x00\x07\x000\x05\x00\x00\x0c\x7f\x1c\x10\x10\x00\x07\x000 @\x00\x0c\x7f\x1c\x07\xc8\x00\x07\x000\x1f\x80\x00\x0c\x7f\x1c_\xf0\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x1f\x98\x00\x07\x001\x7fh\x00\x0c\x7f\x1c\xbf\x9a\x00\x07\x000\xfep\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c?\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c_\xf4\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x07\xc0\x00\x07\x000\x1f\x80\x00\x0c\x7f\x1c\x10\x10\x00\x07\x008 @\x00\x1c\x7f\x0e\x02\x80\x00\x0e\x008\n\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bottom_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00(\x07\x000\x00\x00P\x0c\x7f\x1c\x00\x01\x01\x07\x000\x00\x02\x04\x0c\x7f\x1c\x00\x00|\x87\x000\x00\x01\xf8\x0c\x7f\x1c\x00\x05\xff\x07\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x01\xf9\x87\x000\x00\x17\xf6\x8c\x7f\x1c\x00\x0b\xf9\xa7\x000\x00\x0f\xe7\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x03\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x05\xffG\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x00|\x07\x000\x00\x01\xf8\x0c\x7f\x1c\x00\x01\x01\x07\x008\x00\x02\x04\x1c\x7f\x0e\x00\x00(\x0e\x008\x00\x00\xa0\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Crazy_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x01\x08\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xe0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xe6\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xee\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xfe\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xfe\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x01@\x0c\x7f\x1c\x00\xe0\x00\x07\x000\x00\x08\x10\x0c\x7f\x1c\x01\x08\x00\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xda\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\x9c\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xfa\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x08\x10\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x02\x80\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Crazy_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x04 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x13\x88\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x07\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xda\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x1f\xc8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xbc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x1f\xf8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xfa\x0c\x7f\x1c\x00\xa0\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x04\x04\x00\x07\x000\x00\x13\xc8\x0c\x7f\x1c\x01\xf2\x00\x07\x000\x00\x04 \x0c\x7f\x1c\x17\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xe6\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xe6\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xfe\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x17\xfd\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x01\xf0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x04\x04\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xa0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Disappointed=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x1f\xf8\x00\x07\xfc\x00\x03\xe0\x7f\x07\x80\x00><\x00\x0f\x1e\x00\x00\xf0\x7f\x07\x00\x00|\x1c\x00\x1e\x0f\x00\x00x\x7f\x0e\x00\x00\xf8\x0e\x00\x1c\x07\x80\x008\x7f\x0e\x00\x01\xf0\x0e\x008\x03\xc0\x00\x1c\x7f\x1c\x00\x03\xe0\x07\x008\x01\xe0\x00\x1c\x7f\x1c\x00\x07\xc0\x07\x008\x00\xf0\x00\x1c\x7f\x1c\x00\x0f\x80\x07\x000\x00x\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00>\x00\x07\x000\x00\x1e\x00\x0c\x7f\x1c\x00|@\x07\x000\x00\x9f\x00\x0c\x7f\x1c\x00\xff \x07\x000\x00\x7f\x80\x0c\x7f\x1c\x01\xff\xc0\x07\x000\x00\xff\xc0\x0c\x7f\x1c\x03\xfe`\x07\x000\x05\xfd\xe0\x0c\x7f\x1c\x07\xfeh\x07\x000\x03\xf9\xf0\x0c\x7f\x1c\x0f\xff\xf0\x07\x000\x03\xff\xf8\x0c\x7f\x1c\x1f\xff\xf0\x07\x000\x0b\xff\xfc\x0c\x7f\x1c?\xff\xf0\x07\x000\x03\xff\xde\x0c\x7f\x1c}\xff\xf0\x07\x000\x0b\xff\xdf\x0c\x7f\x1c\xfa\xff\xe8\x07\x000\x03\xff\xc7\x8c\x7f\x1d\xf0\xff\xc0\x07\x000\x05\xff\xa3\xcc\x7f\x1f\xe1\x7f\xd0\x07\x000\x00\xff\x01\xfc\x7f\x1f\xc0\x1f\x00\x07\x000\x00~\x00\xfc\x7f\x1f\x80@@\x07\x000\x00\x81\x00|\x7f\x1f\x00\n\x00\x07\x000\x00(\x00<\x7f\x1e\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dizzy=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x000\x00\x07\x000\x00\xc0\x00\x0c\x7f\x1c\x00\xf0\x00\x07\x000\x03\xc0\x00\x0c\x7f\x1c\x01\xc0\x00\x07\x000\x07\x00\x00\x0c\x7f\x1c\x03\x9f\xe0\x07\x000\x0e\x7f\x80\x0c\x7f\x1c\x07<\xf8\x07\x000\x1c\xf3\xe0\x0c\x7f\x1c\x06`\x1c\x07\x000\x19\x80p\x0c\x7f\x1c\x0c\xc7\xcc\x07\x0003\x1f0\x0c\x7f\x1c\x0c\xcf\xe6\x07\x0003?\x98\x0c\x7f\x1c\r\x98v\x07\x0006a\xd8\x0c\x7f\x1c\r\x9b3\x07\x0006l\xcc\x0c\x7f\x1c\r\x9b\xb3\x07\x0006n\xcc\x0c\x7f\x1c\r\x9f\xb3\x07\x0006~\xcc\x0c\x7f\x1c\x0c\xcf6\x07\x0003<\xd8\x0c\x7f\x1c\x0e\xe0f\x07\x000;\x81\x98\x0c\x7f\x1c\x06y\xee\x07\x000\x19\xe7\xb8\x0c\x7f\x1c\x03\x1f\x8c\x07\x000\x0c~0\x0c\x7f\x1c\x03\x80\x18\x07\x000\x0e\x00`\x0c\x7f\x1c\x00\xf0p\x07\x000\x03\xc1\xc0\x0c\x7f\x1c\x00\x7f\xe0\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x0f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Down=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\n\x00\x07\x000\x00(\x00\x0c\x7f\x1c\x00@@\x07\x000\x00\x81\x00\x0c\x7f\x1c\x00\x9f\x00\x07\x000\x00~\x00\x0c\x7f\x1c\x00\x7f\xd0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x07\x000\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\x7f\xe0\x07\x008\x05\xff\xa0\x1c\x7f\x0e\x01\x7f\xd0\x0e\x008\x00\xff\x00\x1c\x7f\x0e\x00\x1f\x00\x0e\x00<\x00~\x00<\x7f\x0f\x00@@\x1e\x00\x1c\x00\x81\x008\x7f\x07\x80\x15\x00<\x00\x1e\x00\x14\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Evil=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x0f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\xf0\x00\x00<\x00\x0f\x00\x00\x03\xf0\x7f\x07\xf8\x00\x00\x1c\x00\x1e\x00\x00\x07\xf8\x7f\x0e<\x00\x00\x0e\x00\x1c\x00\x00\x0e8\x7f\x0e\x1e\x00\x00\x0e\x008\x00\x00<\x1c\x7f\x1c\x0f\x00\x00\x07\x008\x00\x00x\x1c\x7f\x1c\x07\x80\x00\x07\x008\x00\x00\xf0\x1c\x7f\x1c\x01\xe0\x00\x07\x000\x00\x01\xe0\x0c\x7f\x1c\x00\xf0\x00\x07\x000\x00\x03\xc0\x0c\x7f\x1c\x00x\x00\x07\x000\x00\x07\x80\x0c\x7f\x1c\x00<\x00\x07\x000\x00\x0e\x00\x0c\x7f\x1c\x00\x1e\x00\x07\x000\x00>\x00\x0c\x7f\x1c\x00O\x00\x07\x000\x00|\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x7f\xe0\x07\x000\x01\xfd\xa0\x0c\x7f\x1c\x00\xfe\xf0\x07\x000\x03\xfc\x80\x0c\x7f\x1c\x02\xfe\xf8\x07\x000\x07\xfb\xc0\x0c\x7f\x1c\x01\xff\xfc\x07\x000\x1f\xff\xd0\x0c\x7f\x1c\x01\xff\xfe\x07\x000?\xff\xc0\x0c\x7f\x1c\x01\xff\xff\x07\x000\x7f\xff\xd0\x0c\x7f\x1c\x00\xff\xe3\xc7\x000\xf3\xff\xc0\x0c\x7f\x1c\x02\xff\xe9\xe7\x001\xe1\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\xf7\x003\xc5\xff\xa0\x0c\x7f\x1c\x00?\x80\x7f\x00?\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00?\x00>\x01<\x80\x0c\x7f\x1c\x00\x10\x80\x1f\x00<\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hurt=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x0f\x008\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00?\x00>\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\xff\x00?\x80\x00\x00\x0c\x7f\x1c\x00\x00\x03\xff\x00?\xe0\x00\x00\x0c\x7f\x1c\x00\x00\x0f\xe7\x001\xf8\x00\x00\x0c\x7f\x1c\x00\x00?\x87\x000~\x00\x00\x0c\x7f\x1c\x00\x00\xfe\x07\x000\x1f\x80\x00\x0c\x7f\x1c\x00\x03\xf8\x07\x000\x07\xe0\x00\x0c\x7f\x1c\x00\x0f\xf0\x07\x000\x03\xf8\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x04\xfe\x00\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\x80\x0c\x7f\x1c\x03\xff\xf0\x07\x000\x17\xff\xe0\x0c\x7f\x1c\x0f\xff\x98\x07\x000\x07\xf3\xf8\x0c\x7f\x1c?\xbf\xba\x07\x000\x0f\xef~\x0c\x7f\x1c\xff\x7f\xfc\x07\x000/\xff_\x8c\x7f\x1d\xf8\x7f\xfc\x07\x000\x0f\xff\x07\xec\x7f\x1f\xe0\x7f\xfc\x07\x000/\xffA\xfc\x7f\x1f\x80?\xf8\x07\x000\x0f\xff\x00|\x7f\x1e\x00\xbf\xfa\x07\x008\x07\xfe\x00\x1c\x7f\x0e\x00\x1f\xf0\x0e\x008\x17\xfe\x80\x1c\x7f\x0e\x00\x0f\xe0\x0e\x00<\x03\xfc\x00<\x7f\x0f\x00\x03\x80\x1e\x00\x1c\x04\xf2\x008\x7f\x07\x80\x04 <\x00\x1e\x01\x08\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Knocked_out=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x0f\xff\xfe\x07\x000\x1f\xff\xf8\x0c\x7f\x1c\x0f\xff\xfe\x07\x000?\xff\xfc\x0c\x7f\x1c\x0f\xff\xfe\x07\x000?\xff\xf8\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Love=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xe0\xfc\x07\x000\x0f\x81\xf0\x0c\x7f\x1c\x0f\xd1\xfa\x07\x000\x1fC\xf8\x0c\x7f\x1c\x1f\xeb\xfd\x07\x000?\xa7\xf4\x0c\x7f\x1c\x1f\xff\xfd\x07\x000\x7f\xff\xfa\x0c\x7f\x1c?\xff\xfe\x07\x000\x7f\xff\xfa\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000?\xff\xfc\x0c\x7f\x1c\x0f\xff\xfe\x07\x000\x1f\xff\xf8\x0c\x7f\x1c\x03\xff\xf8\x07\x000\x0f\xff\xf0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x07\xff\xe0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00~\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x04\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Middle_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x08@\x00\x07\x000 \x80\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000\x07 \x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000?\x80\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c?\x98\x00\x07\x000\x7f \x00\x0c\x7f\x1c\xbf\xba\x00\x07\x002\xfe\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c?\xf8\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\x7f\xe0\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000O \x00\x0c\x7f\x1c\x08@\x00\x07\x000\x10\x80\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Middle_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x84\x07\x000\x00\x02\x08\x0c\x7f\x1c\x00\x008\x07\x000\x00\x00r\x0c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x03\xf8\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x03\xf9\x87\x000\x00\x07\xf2\x0c\x7f\x1c\x00\x0b\xfb\xa7\x000\x00\x0f\xef\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xff\x0c\x7f\x1c\x00\x03\xff\x87\x000\x00\x0f\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x07\xfe\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x008\x07\x000\x00\x04\xf2\x0c\x7f\x1c\x00\x00\x84\x07\x000\x00\x01\x08\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Neutral=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x82\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x1c\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xfe\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00\xfe`\x07\x000\x01\xfc\x80\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x01<\x80\x0c\x7f\x1c\x00!\x00\x07\x000\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Nuclear=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x1e\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\xf3\xc0\x07\x000\x01\xe7\x80\x0c\x7f\x1c\x03\x800\x07\x000\x07\x00`\x0c\x7f\x1c\x06\x00\x08\x07\x000\x0c\x00\x10\x0c\x7f\x1c\r\x80$\x07\x000\x1b\x00H\x0c\x7f\x1c\x1b\x80r\x07\x0007\x00\xe4\x0c\x7f\x1c\x13\xc0\xfb\x07\x000'\x81\xf6\x0c\x7f\x1c7\xe0\xfd\x07\x000o\xc1\xfa\x0c\x7f\x1c/\xe1\xfd\x87\x000_\xc3\xfb\x0c\x7f\x1c/\xe1\xfc\x87\x000_\xc3\xf9\x0c\x7f\x1co\xe4\xfe\x87\x000\xdf\xc9\xfd\x0c\x7f\x1cO\xce\xfe\x87\x000\x9f\x9d\xfd\x0c\x7f\x1c@\x1e\x00\x87\x000\x80<\x01\x0c\x7f\x1c@\x0c\x00\x87\x000\x80\x18\x01\x0c\x7f\x1c \x00\x00\x87\x000@\x00\x01\x0c\x7f\x1c \x0e\x00\x87\x000@\x1c\x01\x0c\x7f\x1c \x1f\x01\x87\x000@>\x03\x0c\x7f\x1c\x10?\x01\x07\x000 ~\x02\x0c\x7f\x1c\x18?\x82\x07\x0000\x7f\x04\x0c\x7f\x1c\x08\x7f\x86\x07\x000\x10\xff\x0c\x0c\x7f\x1c\x04\x7f\xcc\x07\x000\x08\xff\x98\x0c\x7f\x1c\x03\x1e\x18\x07\x000\x06<0\x0c\x7f\x1c\x01\xc0`\x07\x000\x03\x80\xc0\x0c\x7f\x1c\x00\x7f\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" +Pinch_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1d\x7f\xbd\x00\x07\x00:\xfe\xfc\x00\x1c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c?\xf8\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\x7f\xe0\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x000\x7f\xe8\x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000\xbf\xd0\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000\x0f\x00\x00\x0c\x7f\x1c\x18`\x00\x07\x0000\xc0\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Pinch_middle=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x05\xfe\xf4\x07\x008\x0b\xfb\xf0\x1c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x02\xff@\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00a\x80\x07\x000\x00\xc3\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Pinch_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x17\xfb\xd7\x008\x00/\xef\\\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xff\x0c\x7f\x1c\x00\x03\xff\x87\x000\x00\x0f\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x07\xfe\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x07\xfe\x8c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x0b\xfd\x0c\x7f\x1c\x00\x008\x07\x000\x00\x00\xf0\x0c\x7f\x1c\x00\x01C\x07\x000\x00\x03\x0c\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tear=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1e\x00\x00\x00\x0f\x008\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\xbf\xa0\x07\x008\x02\xfe@\x1c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x07\x000\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x000\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\xf8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xf6\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfa\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tired_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\xbf\xba\x00\x07\x00:\xfet\x00\x1c\x7f\x1c\x7f\xf8\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x1f\xf8\x00\x07\x009\x7f\xe8\x00\x1c\x7f\x0e_\xf4\x00\x0e\x008?\xc0\x00\x1c\x7f\x0e\x07\xc0\x00\x0e\x00<\x1f\x80\x00<\x7f\x0f\x10\x10\x00\x1e\x00\x1c @\x008\x7f\x07\x85@\x00<\x00\x1e\x05\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tired_middle=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x02\xff\xe8\x07\x008\x0b\xfb\xd0\x1c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x008\x05\xff\xa0\x1c\x7f\x0e\x00?\x80\x0e\x008\x00\xff\x00\x1c\x7f\x0e\x00\x0e\x00\x0e\x00<\x01<\x80<\x7f\x0f\x00!\x00\x1e\x00\x1c\x00B\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Tired_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x0b\xfb\xa7\x008\x00/\xe7\\\x7f\x1c\x00\x07\xff\x87\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x01\xff\x87\x008\x00\x17\xfe\x9c\x7f\x0e\x00\x05\xffN\x008\x00\x03\xfc\x1c\x7f\x0e\x00\x00|\x0e\x00<\x00\x01\xf8<\x7f\x0f\x00\x01\x01\x1e\x00\x1c\x00\x02\x048\x7f\x07\x80\x00(<\x00\x1e\x00\x00Px\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Toxic=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x008\x00\x0c\x7f\x1c\x00\x7f@\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\x00\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\x80\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xc4p\x07\x000\x03\x18\xc0\x0c\x7f\x1c\x01\xc4p\x07\x000\x03\x08\xc0\x0c\x7f\x1c\x00\xce`\x07\x000\x03\x99\xc0\x0c\x7f\x1c\x00\xf9\xe0\x07\x000\x01\xe7\x80\x0c\x7f\x1c\x00y\xc0\x07\x000\x00\xe7\x00\x0c\x7f\x1c\x04\x1f\x02\x07\x000\x18>\x0c\x0c\x7f\x1c\x0f\x8a\x1e\x07\x000?\x10<\x0c\x7f\x1c\x0c\xf0\xf3\x07\x0003\xe1\xec\x0c\x7f\x1c\x00>@\x07\x000\x00|\x00\x0c\x7f\x1c\r\xe3\xe6\x07\x000\x1b\xcf\xc8\x0c\x7f\x1c\x0f\xc0\xfe\x07\x000\x1f\x81\xfc\x0c\x7f\x1c\x06\x00\x0e\x07\x000\x0c\x008\x0c\x7f\x1c\x06\x00\x0c\x07\x000\x08\x00\x18\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Up=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00!\x00\x1c\x00\x1e\x00\x82\x00x\x7f\x0e\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x808\x7f\x0e\x00?\x80\x0e\x008\x00\xfe\x00\x1c\x7f\x1c\x00\x7f\xc0\x07\x008\x05\xff\xa0\x1c\x7f\x1c\x00\xfe`\x07\x008\x01\xfc\x80\x1c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x01<\x80\x0c\x7f\x1c\x00!\x00\x07\x000\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Winking=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x00\x00\x00\x0c\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x00\xff\xe0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' diff --git a/mixly/boards/default_src/micropython/origin/build/lib/gnss.py b/mixly/boards/default_src/micropython/origin/build/lib/gnss.py new file mode 100644 index 00000000..39484a02 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/gnss.py @@ -0,0 +1,91 @@ +""" +GNSS + +Micropython library for the GNSS(NMEA0183/GPS,DBS) +======================================================= +@dahanzimin From the Mixly Team +""" +from time import sleep_ms +from ubinascii import unhexlify + +class NMEA0183: + def __init__(self, uart, baudrate=9600, timeout=200): + self._uart=uart + self._uart.init(baudrate=baudrate, timeout=timeout, rxbuf=1024) + self.time=[None, None, None, None, None, None] + self.locate=['', None, '', None, None, None, None] #0'1经度,2'3纬度,4海拔m,5速度m/s,6航向° + self.status=[False, ' ', 0] #有效标注,定位模式,卫星量 + if not self._chip_id(): + raise AttributeError("Cannot find a GNSS device") + + def _crc8(self, buffer): + '''对数据进行CRC校验''' + crc = 0x00 + for byte in buffer: + crc ^= byte + return crc & 0xff + + def _chip_id(self): + for _ in range(10): + sleep_ms(300) + if self.any(): + self._uart.write(("$PCAS02,1000*2E\r\n").encode()) #更新频率1HZ + self._uart.write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n".encode()) #只加载GNGGA和GNRMC + return True + + def _judge(self, buffer, dlen): + try: + data=buffer.strip().decode().split(',') + if len(data) == dlen: + if unhexlify(data[-1][-2:])[0] == self._crc8(buffer[1:-5]): + return True,data + return False,None + except : + return False,None + + def any(self): + flag_rmc,flag_gga=False,False + while self._uart.any(): + _data=self._uart.readline() + if b'$GNGGA' in _data: + flag_gga,data=self._judge(_data, 15) + #print("GGA----",flag_gga) + if flag_gga: + self.time[3]= int(data[1][0:2]) if data[1] else None + self.time[4]= int(data[1][2:4]) if data[1] else None + self.time[5]= int(data[1][4:6]) if data[1] else None + self.locate[0]= data[5] + self.locate[1]= int(data[4][:3])+int(data[4][3:].replace('.',''))/6000000 if data[4] else None + self.locate[2]= data[3] + self.locate[3]= int(data[2][:2])+int(data[2][2:].replace('.',''))/6000000 if data[2] else None + self.locate[4]= float(data[9]) if data[3] else None + self.status[0]= False if '0' in data[6] else True + self.status[2]= int(data[7]) + if b'$GNRMC' in _data: + flag_rmc,data=self._judge(_data, 14) + #print("RMC----",flag_rmc) + if flag_rmc: + self.time[0]= int(data[9][4:6])+2000 if data[9] else None + self.time[1]= int(data[9][2:4]) if data[9] else None + self.time[2]= int(data[9][0:2]) if data[9] else None + self.time[3]= int(data[1][0:2])+8 if data[1] else None + self.time[4]= int(data[1][2:4]) if data[1] else None + self.time[5]= int(data[1][4:6]) if data[1] else None + self.locate[0]= data[6] + self.locate[1]= int(data[5][:3])+int(data[5][3:].replace('.',''))/6000000 if data[5] else None + self.locate[2]= data[4] + self.locate[3]= int(data[3][:2])+int(data[3][2:].replace('.',''))/6000000 if data[3] else None + self.locate[5]= round(float(data[7])*0.514, 2) if data[7] else None + self.locate[6]= float(data[8]) if data[8] else None + self.status[0]= False if 'V' in data[2] else True + self.status[1]= data[12] + return flag_rmc | flag_gga + + def time(self): + return tuple(self.time) + + def locate(self): + return tuple(self.locate) + + def status(self): + return tuple(self.status) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/hmac.py b/mixly/boards/default_src/micropython/origin/build/lib/hmac.py new file mode 100644 index 00000000..dbbdd471 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/hmac.py @@ -0,0 +1,87 @@ +# Implements the hmac module from the Python standard library. + + +class HMAC: + def __init__(self, key, msg=None, digestmod=None): + if not isinstance(key, (bytes, bytearray)): + raise TypeError("key: expected bytes/bytearray") + + import hashlib + + if digestmod is None: + # TODO: Default hash algorithm is now deprecated. + digestmod = hashlib.md5 + + if callable(digestmod): + # A hashlib constructor returning a new hash object. + make_hash = digestmod # A + elif isinstance(digestmod, str): + # A hash name suitable for hashlib.new(). + make_hash = lambda d=b"": getattr(hashlib, digestmod)(d) + else: + # A module supporting PEP 247. + make_hash = digestmod.new # C + + self._outer = make_hash() + self._inner = make_hash() + + self.digest_size = getattr(self._inner, "digest_size", None) + # If the provided hash doesn't support block_size (e.g. built-in + # hashlib), 64 is the correct default for all built-in hash + # functions (md5, sha1, sha256). + self.block_size = getattr(self._inner, "block_size", 64) + + # Truncate to digest_size if greater than block_size. + if len(key) > self.block_size: + key = make_hash(key).digest() + + # Pad to block size. + key = key + bytes(self.block_size - len(key)) + + self._outer.update(bytes(x ^ 0x5C for x in key)) + self._inner.update(bytes(x ^ 0x36 for x in key)) + + if msg is not None: + self.update(msg) + + @property + def name(self): + return "hmac-" + getattr(self._inner, "name", type(self._inner).__name__) + + def update(self, msg): + self._inner.update(msg) + + def copy(self): + if not hasattr(self._inner, "copy"): + # Not supported for built-in hash functions. + raise NotImplementedError() + # Call __new__ directly to avoid the expensive __init__. + other = self.__class__.__new__(self.__class__) + other.block_size = self.block_size + other.digest_size = self.digest_size + other._inner = self._inner.copy() + other._outer = self._outer.copy() + return other + + def _current(self): + h = self._outer + if hasattr(h, "copy"): + # built-in hash functions don't support this, and as a result, + # digest() will finalise the hmac and further calls to + # update/digest will fail. + h = h.copy() + h.update(self._inner.digest()) + return h + + def digest(self): + h = self._current() + return h.digest() + + def hexdigest(self): + import binascii + + return str(binascii.hexlify(self.digest()), "utf-8") + + +def new(key, msg=None, digestmod=None): + return HMAC(key, msg, digestmod) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/hp203x.py b/mixly/boards/default_src/micropython/origin/build/lib/hp203x.py new file mode 100644 index 00000000..41ee5e7e --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/hp203x.py @@ -0,0 +1,88 @@ +""" +HP203X + +MicroPython library for the HP203X(Air pressure sensor) +======================================================= + +#Changed from circuitpython to micropython 20220211 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +HP203X_ADDRESS = const(0x76) +HP203X_REG_RST = const(0x06) +HP203X_REG_RDY = const(0x0D) +HP20X_READ_P = const(0x30) +HP20X_READ_H = const(0x31) +HP20X_READ_T = const(0x32) +HP20X_READ_CAL = const(0x28) +HP20X_WR_CONVERT_CMD = const(0x40) + +#转换时间 越大时间越久 +#HP20X_CONVERT_OSR4096 =0<<2 +HP20X_CONVERT_OSR2048 =1<<2 +#HP20X_CONVERT_OSR1024 =2<<2 +#HP20X_CONVERT_OSR512 =3<<2 +#HP20X_CONVERT_OSR256 =4<<2 +#HP20X_CONVERT_OSR128 =5<<2 + +class HP203X: + def __init__(self, i2c_bus,cal=False): + self._device = i2c_bus + self._address = HP203X_ADDRESS + self.data_reg = bytearray(3) + self._buffer = bytearray(1) + self.osr = HP20X_CONVERT_OSR2048 #SET time + + if self._read_rdy()&0x40 ==0: + raise AttributeError("Cannot find a HP203X") + + self._rst() #Reset + time.sleep(0.1) + if cal: #Calibration + self._write_cmd(HP20X_WR_CONVERT_CMD|self.osr) + time.sleep(0.1) + self._calibration() + print("calibration") + + def _read_data(self, address): + self._buffer[0] = address & 0xFF + self._device.writeto(self._address,self._buffer) + self._device.readfrom_into(self._address,self.data_reg) + return self.data_reg + + def _write_cmd(self,command): + self._buffer[0] = command & 0xFF + self._device.writeto(self._address,self._buffer) + + def _read_rdy(self): + return self._read_data(HP203X_REG_RDY)[0] + + def _calibration(self): + self._write_cmd(HP20X_READ_CAL) + + def _rst(self): + self._write_cmd(HP203X_REG_RST) + + def u2s(self,n): + return n if n < (1 << 23) else n - (1 << 24) + + def get_data(self,flag): + self._write_cmd(HP20X_WR_CONVERT_CMD|self.osr) + time.sleep(0.1) + self._read_data(flag) + hp_data=(self.data_reg[0]<<16)|(self.data_reg[1]<<8)|self.data_reg[2] + return self.u2s(hp_data)/100 + + def pressure(self): + return self.get_data(HP20X_READ_P) + + def altitude(self): + return self.get_data(HP20X_READ_H) + + def temperature(self): + return self.get_data(HP20X_READ_T) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ht16k33.py b/mixly/boards/default_src/micropython/origin/build/lib/ht16k33.py new file mode 100644 index 00000000..056aecfb --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ht16k33.py @@ -0,0 +1,59 @@ +""" +HT16K33-framebuf + +Micropython library for the HT16K33 Matrix16x8 +======================================================= + +#Preliminary composition 20230411 + +@dahanzimin From the Mixly Team +""" +import uframebuf +from micropython import const + +_HT16K33_BLINK_CMD = const(0x80) +_HT16K33_BLINK_DISPLAYON = const(0x01) +_HT16K33_CMD_BRIGHTNESS = const(0xE0) +_HT16K33_OSCILATOR_ON = const(0x21) + +class HT16K33(uframebuf.FrameBuffer_Ascall): + def __init__(self, i2c, address=0x70, brightness=0.3, width=16, height=8): + self._i2c = i2c + self._address = address + self._blink_rate=0 + self._brightness=brightness + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_HMSB) + self._write_cmd(_HT16K33_OSCILATOR_ON) + self.blink_rate(0) + self.set_brightness(brightness) + self.fill(0) + self.show() + + def _write_cmd(self, val): + '''I2C write command''' + self._i2c.writeto(self._address,val.to_bytes(1, 'little')) + + def blink_rate(self, rate=None): + if rate is None: + return self._blink_rate + if not 0 <= rate <= 3: + raise ValueError("Blink rate must be an integer in the range: 0-3") + rate = rate & 0x03 + self._blink_rate = rate + self._write_cmd(_HT16K33_BLINK_CMD | _HT16K33_BLINK_DISPLAYON | rate << 1) + + def get_brightness(self): + return self._brightness + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0-1.0") + self._brightness = brightness + xbright = round(15 * brightness) + xbright = xbright & 0x0F + self._write_cmd(_HT16K33_CMD_BRIGHTNESS | xbright) + + def show(self): + """Refresh the display and show the changes.""" + self._i2c.writeto_mem(self._address, 0x00, self._buffer) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/huskylens.py b/mixly/boards/default_src/micropython/origin/build/lib/huskylens.py new file mode 100644 index 00000000..4341b901 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/huskylens.py @@ -0,0 +1,305 @@ +""" +HuskyLens + +MicroPython library for the HuskyLens-I2C(DF) +======================================================= + +#Preliminary composition 20220224 +#base on https://github.com/HuskyLens/HUSKYLENSPython 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from ubinascii import unhexlify,hexlify + +commandHeaderAndAddress = "55AA11" +algorthimsByteID = { + "ALGORITHM_OBJECT_TRACKING": "0100", #物体追踪 + "ALGORITHM_FACE_RECOGNITION": "0000", #人脸识别 + "ALGORITHM_OBJECT_RECOGNITION": "0200", #物体识别 + "ALGORITHM_LINE_TRACKING": "0300", #巡线 + "ALGORITHM_COLOR_RECOGNITION": "0400", #颜色识别 + "ALGORITHM_TAG_RECOGNITION": "0500", #标签识别 + "ALGORITHM_OBJECT_CLASSIFICATION": "0600", #物体分类 + "ALGORITHM_QR_CODE_RECOGNTITION" : "0700", #二维码识别(教育版独有) + "ALGORITHM_BARCODE_RECOGNTITION":"0800", #条形码识别(教育版独有) +} + +class Arrow: + def __init__(self, xTail, yTail , xHead , yHead, ID): + self.xTarget=xTail + self.yTarget=yTail + self.xOrigin=xHead + self.yOrigin=yHead + self.id=ID + self.learned= True if ID > 0 else False + self.type="arrows" + +class Block: + def __init__(self, x, y , width , height, ID): + self.xCenter = x + self.yCenter=y + self.width=width + self.height=height + self.id=ID + self.learned= True if ID > 0 else False + self.type="blocks" + +class HuskyLens: + def __init__(self, i2c,address=0x32): + self._address = address + self.checkOnceAgain=True + self._device = i2c + self._buffer=[] + self._learned_number=0 + if not self.knock(): + raise AttributeError("Cannot find a HuskyLens") + + def _write_cmd(self, cmd): + '''Write memory address''' + self._device.writeto(self._address, unhexlify(cmd)) + + def _read_cmd(self, nbytes): + '''Read memory address''' + return self._device.readfrom(self._address, nbytes) + + def _checksum(self, hexStr): + '''data checksums''' + total = 0 + for i in range(0, len(hexStr), 2): + total += int(hexStr[i:i+2], 16) + hexStr = hex(total)[-2:] + return hexStr + + def _read_data(self): + '''Read data''' + while True: + time.sleep(0.01) + buffer = self._read_cmd(5) + if buffer[0] == 0x55: + break + buffer += self._read_cmd(int(buffer[3])+1) + strs=hexlify(buffer).decode() + + headers = strs[0:4] + address = strs[4:6] + data_length = int(strs[6:8], 16) + command = strs[8:10] + if(data_length > 0): + data = strs[10:10+data_length*2] + else: + data = '' + checkSum = strs[2*(6+data_length-1):2*(6+data_length-1)+2] + return [headers, address, data_length, command, data, checkSum] + + def getBlockOrArrowCommand(self): + commandSplit = self._read_data() + isBlock = True if commandSplit[3] == "2a" else False + return (commandSplit[4],isBlock) + + def processReturnData(self): + inProduction = True + byteString="" + if inProduction : + commandSplit = self._read_data() + + if commandSplit[3] == "2e": + return "Knock Recieved" + else: + returnData = [] + numberOfBlocksOrArrow = int(commandSplit[4][2:4]+commandSplit[4][0:2], 16) + self._learned_number = int(commandSplit[4][6:8]+commandSplit[4][4:6], 16) + + for i in range(numberOfBlocksOrArrow): + tmpObj=self.getBlockOrArrowCommand() + isBlock=tmpObj[1] + returnData.append(tmpObj[0]) + + if returnData : + finalData = [] + tmp = [] + for i in returnData: + tmp = [] + for q in range(0, len(i), 4): + low=int(i[q:q+2], 16) + high=int(i[q+2:q+4], 16) + if(high>0): + val=low+255+high + else: + val=low + tmp.append(val) + finalData.append(tmp) + tmp = [] + self.checkOnceAgain=True + self._buffer=self.convert_to_class_object(finalData,isBlock) + return "Data processing completed" + else: + self._buffer=[] + + def convert_to_class_object(self,data,isBlock): + tmp=[] + for i in data: + if(isBlock): + obj = Block(i[0],i[1],i[2],i[3],i[4]) + else: + obj = Arrow(i[0],i[1],i[2],i[3],i[4]) + tmp.append(obj) + return tmp + + def knock(self): + '''Send a simple knock to the HuskyLens to ensure that you are connected and can communicate.''' + self._write_cmd(commandHeaderAndAddress+"002c3c") + return self._read_data()[3] == "2e" + + def command_request_algorthim(self, alg): + '''切换xx算法''' + if alg in algorthimsByteID: + cmd = commandHeaderAndAddress+"022d"+algorthimsByteID[alg] + cmd += self._checksum(cmd) + self._write_cmd(cmd) + return self.processReturnData() + else: + print("INCORRECT ALGORITHIM NAME") + + def command_request(self): + '''请求一次数据 存入结果''' + self._write_cmd(commandHeaderAndAddress+"002030") + self.processReturnData() + + def read_learned_id_count(self): + '''从结果中获取 已学习ID总数''' + return self._learned_number + + def is_appear_direct(self,shape): + '''从结果中获取 方块或箭头 是否在画面中''' + if len(self._buffer) > 0: + return self._buffer[0].type == shape + + + def read_block_center_parameter_direct(self,shape): + '''从结果中获取靠近中心 方块或箭头 的信息''' + if len(self._buffer) > 0: + if self._buffer[0].type == shape : + return self._buffer[0] + else : + return False + + def is_learned(self,get_id): + '''从结果中获取获取IDx是否已学习''' + if 0 < get_id < self._learned_number: + return True + else: + return False + + def is_appear(self,get_id,shape): + '''从结果中获取获取IDx 方块或箭头 是否在画面中''' + if len(self._buffer) > 0: + for i in self._buffer : + if i.id == get_id : + return i.type == shape + + def read_blocks_arrows_parameter(self,get_id,number,shape): + '''从结果中获取获取IDx 第number个方块或箭头 的信息''' + if len(self._buffer) > 0: + id_list=[] + for i in self._buffer : + if i.id == get_id and i.type == shape: + id_list.append(i) + if number is None: + return id_list[0] + else: + return id_list[number-1] + + def read_count(self,get_id,shape): + '''从结果中获取获取IDx 方块或箭头 的总数''' + num=0 + if len(self._buffer) > 0: + for i in self._buffer : + if get_id is None and i.type == shape: + num+=1 + if i.id == get_id and i.type == shape: + num+=1 + return num + + def read_blocks_arrows_parameter_direct(self,number,shape): + '''从结果中获取获取第x个 方块或箭头 的信息''' + if len(self._buffer) >= number : + print(len(self._buffer)) + if self._buffer[number-1].type == shape : + return self._buffer[number-1] + + def command_request_learn_once(self,get_id): + '''自动学习一次 IDx''' + data = "{:04x}".format(get_id) + part1=data[2:] + part2=data[0:2] + #reverse to correct endiness + data=part1+part2 + dataLen = "{:02x}".format(len(data)//2) + cmd = commandHeaderAndAddress+dataLen+"36"+data + print("-----",cmd) + cmd += self._checksum(cmd) + self._write_cmd(cmd) + + def command_request_forget(self): + '''遗忘当前算法的所有学习数据''' + self._write_cmd(commandHeaderAndAddress+"003747") + + def command_request_customnames(self,name,get_id): + '''设置当前算法 IDx 名字为 name''' + nameDataSize = "{:02x}".format(len(name)+1) + name = hexlify(name).decode()+"00" + localId = "{:02x}".format(get_id) + data = localId+nameDataSize+name + dataLen = "{:02x}".format(len(data)//2) + cmd = commandHeaderAndAddress+dataLen+"2f"+data + cmd += self._checksum(cmd) + self._write_cmd(cmd) + + def command_request_custom_text(self,name,x,y): + '''屏幕叠加显示文字name 在 xy''' + name=hexlify(name).decode() + nameDataSize = "{:02x}".format(len(name)//2) + if x>255: + x="ff"+"{:02x}".format(x%255) + else: + x="00"+"{:02x}".format(x) + y="{:02x}".format(y) + data = nameDataSize+x+y+name + dataLen = "{:02x}".format(len(data)//2) + cmd = commandHeaderAndAddress+dataLen+"34"+data + cmd += self._checksum(cmd) + self._write_cmd(cmd) + + def command_request_clear_text(self): + '''清除屏幕显示的文字''' + self._write_cmd(commandHeaderAndAddress+"003545") + + def command_request_photo(self): + '''触发拍照保存到SD卡''' + self._write_cmd(commandHeaderAndAddress+"003040") + time.sleep(0.5) + + def command_request_screenshot(self): + '''触发截屏保存到SD卡''' + self._write_cmd(commandHeaderAndAddress+"003949") + time.sleep(0.5) + + def command_request_save_model_to_SD_card(self,idVal): + '''保存当前算法数据位SD卡 (0~4) 号模型''' + idVal = "{:04x}".format(idVal) + idVal = idVal[2:]+idVal[0:2] + cmd = commandHeaderAndAddress+"0232"+idVal + cmd += self._checksum(cmd) + self._write_cmd(cmd) + time.sleep(0.5) + + def command_request_load_model_from_SD_card(self,idVal): + '''加载当前算法数据位SD卡 (0~4) 号模型''' + idVal = "{:04x}".format(idVal) + idVal = idVal[2:]+idVal[0:2] + cmd = commandHeaderAndAddress+"0233"+idVal + cmd += self._checksum(cmd) + self._write_cmd(cmd) + time.sleep(0.5) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/hx720.py b/mixly/boards/default_src/micropython/origin/build/lib/hx720.py new file mode 100644 index 00000000..4079cdf5 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/hx720.py @@ -0,0 +1,69 @@ +""" +HX720/HX711 + +Micropython library for the HX720/HX711(Load Cell) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from machine import Pin +from micropython import const + +DATA_BITS = const(24) +READY_TIMEOUT_SEC = const(500) + +class HX720: + def __init__(self, sck_pin, dat_pin, scale=500, pulse_obj=1): + self._sck = Pin(sck_pin, Pin.OUT, value=0) + self._dat = Pin(dat_pin, Pin.IN, Pin.PULL_UP) + self._obj = min(max(pulse_obj, 1), 3) + self.scale = scale + self.tare() + + def _wait(self): + """超时响应报错""" + star = time.ticks_ms() + while not self.is_ready(): + if time.ticks_diff(time.ticks_ms(), star) > READY_TIMEOUT_SEC: + raise AttributeError("Cannot find a HX711/HX720") + + def is_ready(self): + """检查是否有数据可以读取""" + return self._dat.value() == 0 + + def set_scale(self, scale): + """设置比例因子""" + self.scale = scale + + def read_raw(self): + """读取传感器的原始数据""" + if not self.is_ready(): + self._wait() + raw_data = 0 + for _ in range(DATA_BITS): + self._sck.value(1) + self._sck.value(0) + raw_data = raw_data << 1 | self._dat.value() + + # 根据脉冲功能设置多读几次 + for _ in range(self._obj): + self._sck.value(1) + self._sck.value(0) + + return raw_data if raw_data < (1 << (DATA_BITS - 1)) else raw_data - (1 << DATA_BITS) + + def tare(self, times=10): + """清零传感器""" + _values = [] + for _ in range(max(times, 5)): + _values.append(self.read_raw()) + _values = sorted(_values)[2: -2] + self.offset = sum(_values) / len(_values) + + def read_weight(self, times=5): + """读取重量数据,返回去掉偏移量的平均值""" + _values = [] + for _ in range(max(times, 3)): + _values.append(self.read_raw()) + _values = sorted(_values)[1: -1] + return round((sum(_values) / len(_values)- self.offset) / self.scale, 2) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/i2cdevice.py b/mixly/boards/default_src/micropython/origin/build/lib/i2cdevice.py new file mode 100644 index 00000000..66ca0b65 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/i2cdevice.py @@ -0,0 +1,280 @@ +""" +I2C_Device + +Micropython library for the I2C communication Device(TD) +======================================================= + +@dahanzimin From the Mixly Team +""" +import random +from machine import SoftI2C + +def _u2s(value, n=8): + return value if value < (1 << (n-1)) else value - (1 << n) + +'''i2c-Inheritance''' +class I2C_device(SoftI2C): + + CRC8_Table =b'\x00^\xbc\xe2a?\xdd\x83\xc2\x9c~ \xa3\xfd\x1fA\x9d\xc3!\x7f\xfc\xa2@\x1e_\x01\xe3\xbd>`\x82\xdc#}\x9f\xc1B\x1c\xfe\xa0\xe1\xbf]\x03\x80\xde> num) + elif value == -1: + self._i2c.write_device(self._addrs[naddr], 0xA0, 0x40 >> num) + except Exception as e: + raise RuntimeError("Cannot find a Traffic lights", e) + +'''LED''' +class LED(Base): + + def brightness(self, naddr=0, value=None): + '''LED灯参数 value: 亮度0~100%, None返回亮度值''' + try: + if value is None: + return self._i2c.read_device(self._addrs[naddr], 0x10) + else: + value = max(min(value, 100), 0) + self._i2c.write_device(self._addrs[naddr], 0xA0, value) + + except Exception as e: + raise RuntimeError("Cannot find a LED device", e) + +class W_LED(LED): + _addrs = [0x38, 0x39, 0x3A, 0x3B] + +class R_LED(LED): + _addrs = [0x3C, 0x3D, 0x3E, 0x3F] + +class Y_LED(LED): + _addrs = [0x40, 0x41, 0x42, 0x43] + +class G_LED(LED): + _addrs = [0x44, 0x45, 0x46, 0x47] + +class B_LED(LED): + _addrs = [0x78, 0x79, 0x7A, 0x7B] + +'''button*5''' +class Buttonx5(Base): + _addrs = [0x68, 0x69, 0x6A, 0x6B] + + def value(self, naddr=0): + '''十字按键返回 (上,下,左,右,中)/bool''' + try: + flag = self._i2c.read_device(self._addrs[naddr], 0x10) + return bool(flag >> 4 & 1), bool(flag >> 3 & 1), bool(flag >> 2 & 1), bool(flag >> 1 & 1), bool(flag & 1) + except Exception as e: + raise RuntimeError("Cannot find a Button sensor", e) + +'''button*1''' +class Button(Base): + _addrs = [0x54, 0x55, 0x56, 0x57] + + def value(self, naddr=0): + '''触碰传感器返回 数值/bool''' + try: + return bool(self._i2c.read_device(self._addrs[naddr], 0x10)) + except Exception as e: + raise RuntimeError("Cannot find a Touch sensor", e) + +'''Infrared sensor''' +class Infrared(Base): + _addrs = [0x6C, 0x6D, 0x6E, 0x6F] + + def value(self, naddr=0): + '''红外接近返回 数值0~100%''' + try: + return self._i2c.read_device(self._addrs[naddr], 0x10) + except Exception as e: + raise RuntimeError("Cannot find a Infrared sensor", e) + +'''ultrasonic sensor''' +class Sonar(Base): + _addrs = [0x24, 0x25, 0x26, 0x27] + _state = 0x00 + def value(self, naddr=0): + '''超声波测距返回 距离数值cm''' + try: + value = self._i2c.read_device(self._addrs[naddr], 0x10, 2) + return value[0] << 8 | value[1] + except Exception as e: + raise RuntimeError("Cannot find a Ultrasonic sensor", e) + + def led(self, naddr=0, num=0, value=0): + '''超声波指示灯参数 num:序号0~3,value:0灭,1亮,-1反转 ''' + try: + if value > 0: + self._state |= 1 << num + elif value < 0: + self._state ^= 1 << num + else: + self._state &= ~ (1 << num) + self._i2c.write_device(self._addrs[naddr], 0xA0, bytearray([self._state & 0xff, 0x00])) + except Exception as e: + raise RuntimeError("Cannot find a Ultrasonic sensor", e) + +'''Potentiometer''' +class Dimmer(Base): + _addrs = [0x2C, 0x2D, 0x2E, 0x2F] + + def value(self, naddr=0): + '''旋钮传感器返回 数值0~100%''' + try: + return self._i2c.read_device(self._addrs[naddr], 0x10) + except Exception as e: + raise RuntimeError("Cannot find a Potentiometer", e) + +'''Color sensor''' +class Color_ID(Base): + _id = ('Black', 'Violet', 'Unknown', 'Blue', 'Cyan', 'Green', 'Unknown', 'Yellow', 'Unknown', 'Red', 'White', 'Unknown') + _addrs = [0x20, 0x21, 0x22, 0x23] + + def recognition(self, naddr=0): + '''颜色识别返回 (颜色名,(R,G,B),环境亮度0~100,反射亮度0~100)''' + try: + color = self._i2c.read_device(self._addrs[naddr], 0x10, 6) + return self._id[min(color[0],11)], (color[1],color[2],color[3]), color[4], color[5] + except Exception as e: + raise RuntimeError("Cannot find a Color sensor", e) + +'''Laser Sensor''' +class TOF(Base): + _addrs = [0x5C, 0x5D, 0x5E, 0x5F] + + def value(self, naddr=0): + '''激光测距传感器返回 数值cm''' + try: + flag = self._i2c.read_device(self._addrs[naddr], 0x10, 2) + return (flag[0] << 8 | flag[1]) / 100 + except Exception as e: + raise RuntimeError("Cannot find a Laser Sensor", e) + + def enable(self, naddr=0, en=True): + '''激光测距传感器 en:0关闭,1打开''' + try: + self._i2c.write_device(self._addrs[naddr], 0xA0, int(en) & 0x01) + except Exception as e: + raise RuntimeError("Cannot find a Laser Sensor", e) + +'''Servo Motor''' +class Motor_servo(Base): + _addrs = [0x60, 0x61, 0x62, 0x63] + _mstop = [0, 0, 0, 0] + + def stop_mode(self, naddr=0, mode=0): + '''电机停止模式 mode:0,保持位置 1,惯性滑行 2,阻力制动''' + self._mstop[naddr] = mode + + def _write(self, naddr=0, mode=0, value=0, direction=0, angle=0, origin=0, keep=0, select=0): + '''寄存器参数设置''' + try: + _bytes1 = direction<<6 | mode<<5 | select<<4 | origin<<3 | keep<<2 | self._mstop[naddr] + _bytes2 = max(min(value, 100), 0) + _bytes3 = angle & 0xFF + _bytes4 = angle>>8 & 0xFF + _bytes5 = angle>>16 & 0xFF + self._i2c.write_device(self._addrs[naddr], 0xA0, bytearray([_bytes1, _bytes2, _bytes3, _bytes4, _bytes5])) + except Exception as e: + raise RuntimeError("Cannot find a Servo Motor", e) + + def absolute_run(self, naddr=0, mode=0, value=50, direction=0, angle=0): + ''' 绝对角度运行模式(类舵机) + 运行模式mode 0:速度模式,1:功率模式 + 模式数值value 0~100% + 转向设置direction 0:顺时针,1:最短路径,2:逆时针 + 旋转角度angle 0~360° + ''' + self._write(naddr=naddr, mode=mode, value=value, direction=direction, angle=angle, select=0) + + def relative_run(self, naddr=0, mode=0, value=50, angle=0): + ''' 相对角度运行模式(类编码电机) + 运行模式mode 0:速度模式,1:功率模式 + 模式数值value 0~100% + 旋转角度angle -8388607~8388607° + ''' + self._write(naddr=naddr, mode=mode, value=value, angle=angle, select=1) + + def relative_origin(self, naddr=0): + '''当前位置设置为原点''' + self._write(naddr=naddr, origin=1, select=1) + + def relative_continue(self, naddr=0, mode=0, value=50, direction=0): + ''' 相对角度运行模式(类普通电机) + 运行模式mode 0:速度模式,1:功率模式 + 模式数值value 0~100% + 转向设置direction 0:顺时针,2:逆时针 + ''' + self._write(naddr=naddr, mode=mode, value=value, direction=direction, keep=1, select=1) + + def stop(self, naddr=0): + '''电机停止''' + self._write(naddr=naddr, keep=1) + + def state(self,naddr=0): + '''运行状态返回 (功率, 速度, 绝对角度, 相对角度, 是否堵住, 是否转完) ''' + try: + _buf = self._i2c.read_device(self._addrs[naddr], 0x10, 7) + return _u2s(_buf[0]), _u2s(_buf[1]), (_buf[2] & 0x01)<<8 | _buf[3], _u2s((_buf[4]<<16 | _buf[5]<<8 | _buf[6]),24), bool(_buf[2] & 0x40), bool(_buf[2] & 0x80) + except Exception as e: + raise RuntimeError("Cannot find a Servo Motor", e) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/i2clcd.py b/mixly/boards/default_src/micropython/origin/build/lib/i2clcd.py new file mode 100644 index 00000000..381f9a40 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/i2clcd.py @@ -0,0 +1,79 @@ +""" +LCD1602、LCD2004_I2C + +Micropython library for the I2C(LCD1602、LCD2004) +======================================================= + +#Preliminary composition 20221117 + +dahanzimin From the Mixly Team +""" +from time import sleep_ms +from micropython import const + +LCD_DAT = const(0x01) # Mode - Sending data +LCD_CMD = const(0x00) # Mode - Sending command +LCD_LINES = (0x80, 0xC0, 0x94, 0xD4) + +class LCD(): + def __init__(self, i2c_bus, i2c_addr=0x27, lcd_width=16): + self._device = i2c_bus + self._address = i2c_addr + self._lcd_width = lcd_width + self._backlight = True + self._last_data = 0x00 + + for i in [0x30, 0x30, 0x30,0x20]: + self._i2c_write(i) + sleep_ms(1) + for i in [0x28, 0x0C, 0x06]: + self.write_byte(i , LCD_CMD) + self.clear() + + def _i2c_write(self, data , pulse_en=True): + """write one byte to I2C bus""" + self._last_data = data + self._device.writeto(self._address,data.to_bytes(1, 'little')) + sleep_ms(0) + if pulse_en : + self._device.writeto(self._address,(data | 0b00000100).to_bytes(1, 'little')) + sleep_ms(0) + self._device.writeto(self._address,(data & ~0b00000100).to_bytes(1, 'little')) + sleep_ms(0) + + def write_byte(self, data, mode): + """write one byte to LCD""" + data_H = (data & 0xF0) | self._backlight * 0x08 | mode + data_L = ((data << 4) & 0xF0) | self._backlight * 0x08 | mode + self._i2c_write(data_H) + self._i2c_write(data_L) + + def clear(self): + """Clear the display and reset the cursor position""" + self.write_byte(0x01, LCD_CMD) + sleep_ms(1) + + def backlight(self, on_off): + """ Set whether the LCD backlight is on or off""" + self._backlight = on_off & 0x01 + i2c_data = (self._last_data & 0xF7) + self._backlight * 0x08 + self._i2c_write(i2c_data,pulse_en=False) + + def shows(self, text, line=0, column=0, center=False): + '''Character display''' + text = str(text).encode('ascii') + column=(self._lcd_width-len(text))//2 if center else column + self.write_byte(LCD_LINES[line] + column, LCD_CMD) + for b in text: + self.write_byte(0x0C+0*0x02+0*0x01, LCD_CMD) + self.write_byte(b, LCD_DAT) + + def print(self, text, line=0, column=0, delay=500): + '''Print Effect Character Display''' + text = str(text).encode('ascii') + self.write_byte(LCD_LINES[line] + column, LCD_CMD) + for b in text: + self.write_byte(0x0C+1*0x02+1*0x01, LCD_CMD) + sleep_ms(delay) + self.write_byte(b, LCD_DAT) + sleep_ms(delay) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/icm42670.py b/mixly/boards/default_src/micropython/origin/build/lib/icm42670.py new file mode 100644 index 00000000..9d5c644a --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/icm42670.py @@ -0,0 +1,94 @@ +""" +ICM42670P + +Micropython library for the ICM42670P(Accelerometer+Gyroscope) +======================================================= + +#Preliminary composition 20220716 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +ICM42670_REG_DEVICE_ID = const(0x00) +ICM42670_REG_RESET = const(0x02) +ICM42670_REG_DATA = const(0x09) +ICM42670_REG_PWR_MGMT0 = const(0x1F) +ICM42670_REG_GYRO_CONFIG0 = const(0x20) +ICM42670_REG_ACCEL_CONFIG0 = const(0x21) +ICM42670_REG_APEX_DATA0 = const(0x31) +ICM42670_REG_WHO_AM_I = const(0x75) + +AccRange_16g = 0 +AccRange_8g = 1 +AccRange_4g = 2 +AccRange_2g = 3 + +GyrRange_2000dps = 0 +GyrRange_1000dps = 1 +GyrRange_500dps = 2 +GyrRange_250dps = 3 + +Acc_Gyr_Odr_1600Hz = 0x05 +Acc_Gyr_Odr_800Hz = 0x06 +Acc_Gyr_Odr_400Hz = 0x07 +Acc_Gyr_Odr_200Hz = 0x08 +Acc_Gyr_Odr_100Hz = 0x09 +Acc_Gyr_Odr_50Hz = 0x0A +Acc_Gyr_Odr_25Hz = 0x0B +Acc_Gyr_Odr_12_5Hz = 0x0C + +class ICM42670: + def __init__(self, i2c_bus, addr=0x68, AccRange=AccRange_16g, GyrRange=GyrRange_2000dps, Acc_Gyr_Odr=Acc_Gyr_Odr_100Hz): + self._device = i2c_bus + self._address = addr + if self._chip_id() != 0x67: + raise AttributeError("Cannot find a ICM42670") + + self._wreg(ICM42670_REG_RESET,0x10) #Software reset enabled + time.sleep(0.1) + self._wreg(ICM42670_REG_GYRO_CONFIG0,(GyrRange << 4) | Acc_Gyr_Odr) #Gyr-500HZ/2000dps + self._wreg(ICM42670_REG_ACCEL_CONFIG0,(AccRange << 4) | Acc_Gyr_Odr) #ACC-100HZ/16G + self._wreg(ICM42670_REG_PWR_MGMT0,0x1E) + time.sleep(0.1) + self.acc_lsb_div= 2 ** (11 + AccRange) + self.gyr_lsb_div= 2 ** (14 + GyrRange) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(ICM42670_REG_WHO_AM_I) + + def u2s(self,n): + return n if n < (1 << 15) else n - (1 << 16) + + def getdata(self): + _buffer=self._rreg(ICM42670_REG_DATA,14) + tmp= float(self.u2s(_buffer[0]<<8|_buffer[1]))/128+25 + acc_x=float(self.u2s(_buffer[2]<<8|_buffer[3]))/self.acc_lsb_div + acc_y=float(self.u2s(_buffer[4]<<8|_buffer[5]))/self.acc_lsb_div + acc_z=float(self.u2s(_buffer[6]<<8|_buffer[7]))/self.acc_lsb_div + gyr_x=float(self.u2s(_buffer[8]<<8|_buffer[9]))/self.gyr_lsb_div + gyr_y=float(self.u2s(_buffer[10]<<8|_buffer[11]))/self.gyr_lsb_div + gyr_z=float(self.u2s(_buffer[12]<<8|_buffer[13]))/self.gyr_lsb_div + return (acc_x,acc_y,acc_z),(gyr_x,gyr_y,gyr_z),round(tmp,2) + + def accelerometer(self): + return self.getdata()[0] + + def strength(self): + from math import sqrt + return sqrt(self.accelerometer()[0]**2+self.accelerometer()[1]**2+self.accelerometer()[2]**2) + + def gyroscope(self): + return self.getdata()[1] + + def temperature(self): + return self.getdata()[2] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/image.py b/mixly/boards/default_src/micropython/origin/build/lib/image.py new file mode 100644 index 00000000..60c037b3 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/image.py @@ -0,0 +1,87 @@ +""" +Iamge + +MicroPython library for the Iamge(jpeg C module) +======================================================= +@dahanzimin From the Mixly Team +""" +import gc +import urequests +from base64 import b64encode +from jpeg import Encoder, Decoder + +class IMG: + def __init__(self, image, width, height): + self.image = image + self.width = width + self.height = height + self.format = "RGB565" + +class Image: + def save(self, img, path="mixly.jpg", **kwargs): + '''quality(1-100), rotation (0, 90, 180, 270)''' + _encoder = Encoder(pixel_format="RGB565_BE", width=img.width, height=img.height, **kwargs) + _jpeg = _encoder.encode(img.image) + del _encoder + gc.collect() + if isinstance(path, str): + with open(path, 'wb') as f: + f.write(_jpeg) + else: + return _jpeg + + def open(self, path="mixly.jpg", scale_width=None, scale_height=None, tft_width=240, tft_height=240, **kwargs): + '''rotation (0, 90, 180, 270), clipper_width, clipper_height''' + with open(path, "rb") as f: + _jpeg = f.read() + return self._jpg_decoder(_jpeg, scale_width, scale_height, tft_width, tft_height, **kwargs) + + def convert(self, img, formats=0, **kwargs): + if formats == 0: + return self.save(img, None, **kwargs) + elif formats == 1: + return b'data:image/jpg;base64,' + b64encode(self.save(img, None, **kwargs)) + + def download(self, url, path=None, scale_width=None, scale_height=None, tft_width=240, tft_height=240, block=1024, **kwargs): + '''rotation (0, 90, 180, 270), clipper_width, clipper_height''' + response = urequests.get(url, stream=True) + if path is None: + _image = self._jpg_decoder(response.raw.read(), scale_width, scale_height, tft_width, tft_height, **kwargs) + response.close() + return _image + else: + with open(path, 'wb') as f: + while True: + _data = response.raw.read(block) + if not _data: + break + else: + f.write(_data) + response.close() + + def _jpg_decoder(self, jpg, scale_width, scale_height, tft_width, tft_height, **kwargs): + '''Automatically zoom based on the screen''' + if scale_width is None or scale_height is None: + _width = tft_width + _height = tft_height + for i in range(min(len(jpg), 1024)): + if jpg[i] == 0xFF and (jpg[i + 1] & 0xF0) == 0xC0: + if jpg[i + 1] not in [0xC4, 0xC8, 0xCC]: + _width = jpg[i + 7] << 8 | jpg[i + 8] + _height = jpg[i + 5] << 8| jpg[i + 6] + break + if _width > tft_width or _height > tft_height: + _scale = max(_width / tft_width, _height / tft_height) * 8 + _decoder = Decoder(pixel_format="RGB565_BE", scale_width=round(_width / _scale) * 8, scale_height=round(_height / _scale) * 8, **kwargs) + else: + _decoder = Decoder(pixel_format="RGB565_BE", **kwargs) + else: + _decoder = Decoder(pixel_format="RGB565_BE", scale_width=scale_width // 8 * 8, scale_height=scale_height // 8 * 8, **kwargs) + _info = _decoder.get_img_info(jpg) + _image = IMG(_decoder.decode(jpg), _info[0], _info[1]) + del _decoder, jpg + gc.collect() + return _image + +#图像处理 +Image = Image() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/informatio_picture.py b/mixly/boards/default_src/micropython/origin/build/lib/informatio_picture.py new file mode 100644 index 00000000..26dc192e --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/informatio_picture.py @@ -0,0 +1,18 @@ +#Take the picture bytes in informatio_picture.py +#--dahanzimin From the Mixly Team + +Accept=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x8c\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x01\xa7\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x03y\x80\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x02~`\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x04\xff0\x00\x7f\x00\x00\x00\x00\x00\x00\x00\t\xff\xec\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x1b\xff\xf6\x00\x7f\x00\x00\x00\x00\x00\x00\x007\xff\xfd\x80\x7f\x00\x00\x00\x00\x00\x00\x00o\xff\xff\x80\x7f\x00\x00\x00\x00\x00\x00\x00_\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x9f\xff\xfe\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xbf\xff\xfc\x00\x7f\x00\x00\x00\x00\x00\x00\x03\x7f\xff\xf8\x00\x7f\x00\x00\x00\x00\x00\x00\x06\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\x00\x05\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x00\x0b\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00\x00\x17\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x007\xff\xfe\x00\x00\x7f\x00\x00\x00\x00\x00\x00o\xff\xfc\x00\x00\x7f\x00\x00\x00\x00\x00\x00_\xff\xf8\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xbf\xff\xf0\x00\x00\x7f\x00\x00\x00\x00\x00\x01\x7f\xff\xe0\x00\x00\x7f\x00\x00\x00\x00\x00\x03\x7f\xff\xc0\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\r\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0b\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00/\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xf0\x00\x00\x00\x7f\x00\x00\x01\xc0\x00\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x1e@\x00\xff\xff\xc0\x00\x00\x00\x7f\x00\x01\xeb \x01\xff\xff\x80\x00\x00\x00\x7f\x00\x1e\xff\xa0\x03\xff\xff\x00\x00\x00\x00\x7f\x00w\xff\xb0\x07\xff\xfe\x00\x00\x00\x00\x7f\x00?\xff\x90\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x1f\xff\xd0\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x1f\xff\xf8\x1f\xff\xf0\x00\x00\x00\x00\x7f\x00\x0f\xff\xe8?\xff\xe0\x00\x00\x00\x00\x7f\x00\x07\xff\xf8\x7f\xff\xc0\x00\x00\x00\x00\x7f\x00\x03\xff\xf4\xff\xff\x80\x00\x00\x00\x00\x7f\x00\x03\xff\xfd\xff\xff\x00\x00\x00\x00\x00\x7f\x00\x01\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x7f\x00\x00\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x7f\x00\x00\x7f\xff\xff\xf8\x00\x00\x00\x00\x00\x7f\x00\x00\x7f\xff\xff\xf0\x00\x00\x00\x00\x00\x7f\x00\x00?\xff\xff\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x1f\xff\xff\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x0f\xff\xff\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\xff\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x03\xff\xf8\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x01\xff\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xff\xe0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Backward=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0b\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xf7\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xfdW\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xf2\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xe4\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xe8\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xd8\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xa0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff@\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xfd\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Decline=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\x05\x00\x00\x00\x7f\x00\x00\x00\xfc\x00\x00\x00\x0f\x80\x00\x00\x7f\x00\x00\x01\xfe\x00\x00\x00\x17\xc0\x00\x00\x7f\x00\x00\x03\xff\x00\x00\x00?\xa0\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00_\xf0\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x00\xff\xe8\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x01\x7f\xfc\x00\x00\x7f\x00\x00?\xff\xf0\x00\x03\xff\xfa\x00\x00\x7f\x00\x00\x7f\xff\xf8\x00\x05\xff\xff\x00\x00\x7f\x00\x00\xff\xff\xfc\x00\x0f\xff\xfe\x80\x00\x7f\x00\x01\xff\xff\xfe\x00\x17\xff\xff\xc0\x00\x7f\x00\x01\xff\xff\xff\x00?\xff\xff\xc0\x00\x7f\x00\x00\xff\xff\xff\x80_\xff\xff\x80\x00\x7f\x00\x00\x7f\xff\xff\xc0\xff\xff\xff\x00\x00\x7f\x00\x00?\xff\xff\xe1\x7f\xff\xfe\x00\x00\x7f\x00\x00\x1f\xff\xff\xf3\xff\xff\xfc\x00\x00\x7f\x00\x00\x0f\xff\xff\xfd\xff\xff\xf8\x00\x00\x7f\x00\x00\x07\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x03\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x00\xff\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x0b\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00/\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\xbf\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\x02\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x07\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0b\xff\xff\xf7\xff\xff\xfc\x00\x00\x7f\x00\x00\x1f\xff\xff\xe3\xff\xff\xfe\x00\x00\x7f\x00\x00/\xff\xff\xc1\xff\xff\xff\x00\x00\x7f\x00\x00\x7f\xff\xff\x80\xff\xff\xff\x80\x00\x7f\x00\x00\xbf\xff\xff\x00\x7f\xff\xff\xc0\x00\x7f\x00\x01\xff\xff\xfe\x00?\xff\xff\xc0\x00\x7f\x00\x00\xff\xff\xfc\x00\x1f\xff\xff\xc0\x00\x7f\x00\x00\x7f\xff\xf8\x00\x0f\xff\xff\x80\x00\x7f\x00\x00?\xff\xf0\x00\x07\xff\xff\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x03\xff\xfe\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x01\xff\xfc\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00\xff\xf8\x00\x00\x7f\x00\x00\x03\xff\x00\x00\x00\x7f\xf0\x00\x00\x7f\x00\x00\x01\xfe\x00\x00\x00?\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00\x00\x00\x1f\xc0\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\x0f\x80\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x07\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Forward=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00+\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00]\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xdc\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xbe\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x7f`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x02\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x90\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05\xff\xd8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xec\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x17\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xf2\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfb\x00\x00\x00\x00\x7f\x00\x00\x00\x00_\xff\xfd\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xfe@\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff`\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xd0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xc8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xec\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xf4\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf2\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01>\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x06~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\r\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x13\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00g\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xdf\xff\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x01?\xffUUUUX\x00\x7f\x00\x00\x06\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xff\xe8\x00\x7f\x00\x00\x17\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x01\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x01\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x1f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x03\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x00\xff\xff\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00?\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1f\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +No_go=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xfc>\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xc3\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xf8`\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\x18\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xcc\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf3\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xc1\xff\xfd\x80\x00\x00\x7f\x00\x00\x00\xff\xfc\x00\x1f\xfc\xc0\x00\x00\x7f\x00\x00\x01\xff\xf0\x00\x03\xff`\x00\x00\x7f\x00\x00\x03\xff\xc0\x00\x00\xf7\xb0\x00\x00\x7f\x00\x00\x07\xff\x00\x00\x00\x7f\xd0\x00\x00\x7f\x00\x00\x0f\xfe\x00\x00\x00_\xe8\x00\x00\x7f\x00\x00\x0f\xf8\x00\x00\x00\xff\xf4\x00\x00\x7f\x00\x00\x1f\xf0\x00\x00\x01\x7f\xf4\x00\x00\x7f\x00\x00?\xf0\x00\x00\x03\xff\xfa\x00\x00\x7f\x00\x00?\xe0\x00\x00\x05\xff\xfb\x00\x00\x7f\x00\x00\x7f\xc0\x00\x00\x0f\xfd\xfd\x00\x00\x7f\x00\x00\x7f\xc0\x00\x00\x17\xf8\xfd\x00\x00\x7f\x00\x00\x7f\x80\x00\x00?\xf0\xff\x80\x00\x7f\x00\x00\xff\x80\x00\x00_\xe0~\x80\x00\x7f\x00\x00\xff\x00\x00\x00\xff\xc0\x7f\x80\x00\x7f\x00\x00\xff\x00\x00\x01\x7f\x80?@\x00\x7f\x00\x00\xfe\x00\x00\x03\xff\x00?@\x00\x7f\x00\x01\xfe\x00\x00\x05\xfe\x00?@\x00\x7f\x00\x01\xfe\x00\x00\x0f\xfc\x00\x1f\xc0\x00\x7f\x00\x01\xfe\x00\x00\x17\xf8\x00\x1f\xc0\x00\x7f\x00\x01\xfc\x00\x00?\xf0\x00\x1f\xe0\x00\x7f\x00\x01\xfc\x00\x00_\xe0\x00\x1f\xa0\x00\x7f\x00\x01\xfc\x00\x00\xff\xc0\x00\x1f\xe0\x00\x7f\x00\x01\xfc\x00\x01\x7f\x80\x00\x1f\xa0\x00\x7f\x00\x01\xfc\x00\x03\xff\x00\x00\x1f\xe0\x00\x7f\x00\x01\xfe\x00\x05\xfe\x00\x00\x1f\xe0\x00\x7f\x00\x01\xfe\x00\x0f\xfc\x00\x00\x1f\xc0\x00\x7f\x00\x01\xfe\x00\x17\xf8\x00\x00?\xc0\x00\x7f\x00\x01\xfe\x00?\xf0\x00\x00?\xc0\x00\x7f\x00\x00\xff\x00_\xe0\x00\x00?\xc0\x00\x7f\x00\x00\xff\x00\xff\xc0\x00\x00\x7f\xc0\x00\x7f\x00\x00\xff\x01\xff\x80\x00\x00\x7f\x80\x00\x7f\x00\x00\xff\x83\xff\x00\x00\x00\x7f\x80\x00\x7f\x00\x00\x7f\x87\xfe\x00\x00\x00\xff\x80\x00\x7f\x00\x00\x7f\xcf\xfc\x00\x00\x01\xff\x00\x00\x7f\x00\x00?\xff\xf8\x00\x00\x01\xff\x00\x00\x7f\x00\x00?\xff\xf0\x00\x00\x03\xfe\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x00\x07\xfe\x00\x00\x7f\x00\x00\x1f\xff\xc0\x00\x00\x07\xfc\x00\x00\x7f\x00\x00\x0f\xff\x80\x00\x00\x1f\xfc\x00\x00\x7f\x00\x00\x07\xff\x00\x00\x00?\xf8\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00\xff\xf0\x00\x00\x7f\x00\x00\x03\xff\xe0\x00\x01\xff\xe0\x00\x00\x7f\x00\x00\x01\xff\xf8\x00\x0f\xff\xc0\x00\x00\x7f\x00\x00\x00\xff\xff\x00\x7f\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Question_mark=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\x1e\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xe3\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfc\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xc8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xe4\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xf1\xff\xf2\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\x80\x7f\xf9\x00\x00\x00\x7f\x00\x00\x00?\xfe\x00\x1f\xfd\x00\x00\x00\x7f\x00\x00\x00?\xfc\x00\x07\xfd\x80\x00\x00\x7f\x00\x00\x00?\xf8\x00\x07\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf8\x00\x03\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x03\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x01\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xe0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xe0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x03\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x07\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x01\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xfd\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xfe\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff@\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00&\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00,\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?`\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00/\xb0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xcc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00/\xf6\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfb\x00\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xef\xfc\xc0\x00\x00\x7f\x00\x05UUUU_\xff`\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xb0\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xcc\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf6\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfb\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfc\xc0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff`\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xb0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xb0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfe`\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfc\x80\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfb\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf6\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xb0\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff`\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xf0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Stop_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xfc\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x07\x80\x00\x00\xd0\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00h\x00\x00\x00\x7f\x00\x00\x00\x1e\x7f\xff\xff4\x00\x00\x00\x7f\x00\x00\x00<\xff\xff\xff\x9a\x00\x00\x00\x7f\x00\x00\x00y\xff\xff\xff\xcd\x00\x00\x00\x7f\x00\x00\x00\xf3\xff\xff\xff\xe6\x80\x00\x00\x7f\x00\x00\x01\xe7\xff\xff\xff\xf3@\x00\x00\x7f\x00\x00\x03\xcf\xff\xff\xff\xf9\xa0\x00\x00\x7f\x00\x00\x07\x9f\xff\xff\xff\xfc\xd0\x00\x00\x7f\x00\x00\x0f?\xff\xff\xff\xfeh\x00\x00\x7f\x00\x00\x1e\x7f\xff\xff\xff\xff4\x00\x00\x7f\x00\x00<\xff\xff\xff\xff\xff\x9a\x00\x00\x7f\x00\x00y\xff\xff\xff\xff\xff\xcd\x00\x00\x7f\x00\x00\xf3\xff\xff\xff\xff\xff\xe6\x80\x00\x7f\x00\x01\xe7\xff\xff\xff\xff\xff\xf3@\x00\x7f\x00\x03\xcf\xff\xff\xff\xff\xff\xf9\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\x9e\x0f\x00<\x0f\xc0<\xa0\x00\x7f\x00\x03\x9c\x02\x00\x18\x07\x80\x0c\xa0\x00\x7f\x00\x03\x98\x02\x00\x10\x03\x80\x04\xa0\x00\x7f\x00\x03\x90\xe1\xe0\xf1\xe3\x8f\xc4\xa0\x00\x7f\x00\x03\x91\xf7\xf1\xe3\xf1\x8f\xe4\xa0\x00\x7f\x00\x03\x91\xff\xf1\xe3\xf1\x8f\xe0\xa0\x00\x7f\x00\x03\x98\xff\xf1\xc7\xf9\x8f\xe4\xa0\x00\x7f\x00\x03\x98?\xf1\xc7\xf8\x8f\xc4\xa0\x00\x7f\x00\x03\x9c\x0f\xf1\xc7\xf8\x87\x84\xa0\x00\x7f\x00\x03\x9e\x03\xf1\xc7\xf8\x80\x0c\xa0\x00\x7f\x00\x03\x9f\x81\xf1\xc7\xf8\x80\x1c\xa0\x00\x7f\x00\x03\x9f\xe1\xf1\xc7\xf8\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf1\xf1\xc7\xf8\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf8\xf1\xe3\xf1\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf8\xf1\xe3\xf1\x87\xfc\xa0\x00\x7f\x00\x03\x91\xf1\xf1\xe1\xe1\x87\xfc\xa0\x00\x7f\x00\x03\x90\x01\xf1\xf0\xc3\x87\xfc\xa0\x00\x7f\x00\x03\x98\x01\xf1\xf8\x07\x87\xfc\xa0\x00\x7f\x00\x03\x9c\x07\xf1\xfc\x0f\x87\xfc\xa0\x00\x7f\x00\x03\x9f\x1f\xff\xff?\xff\xfc\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\xcf\xff\xff\xff\xff\xff\xf9\xa0\x00\x7f\x00\x01\xe7\xff\xff\xff\xff\xff\xf3@\x00\x7f\x00\x00\xf3\xff\xff\xff\xff\xff\xe6\x80\x00\x7f\x00\x00y\xff\xff\xff\xff\xff\xcd\x00\x00\x7f\x00\x00<\xff\xff\xff\xff\xff\x9a\x00\x00\x7f\x00\x00\x1e\x7f\xff\xff\xff\xff4\x00\x00\x7f\x00\x00\x0f?\xff\xff\xff\xfeh\x00\x00\x7f\x00\x00\x07\x9f\xff\xff\xff\xfc\xf0\x00\x00\x7f\x00\x00\x03\xcf\xff\xff\xff\xf9\xe0\x00\x00\x7f\x00\x00\x01\xe7\xff\xff\xff\xf3\xc0\x00\x00\x7f\x00\x00\x00\xf3\xff\xff\xff\xe7\x80\x00\x00\x7f\x00\x00\x00y\xff\xff\xff\xcf\x00\x00\x00\x7f\x00\x00\x00<\xff\xff\xff\x9e\x00\x00\x00\x7f\x00\x00\x00\x1e\x7f\xff\xff<\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00x\x00\x00\x00\x7f\x00\x00\x00\x07\x80\x00\x00\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Stop_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xfc\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x07\xc0\x00\x00\xd0\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00h\x00\x00\x00\x7f\x00\x00\x00\x1e\x00\x00\x004\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1a\x00\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\r\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x06\x80\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x03@\x00\x00\x7f\x00\x00\x03\xc0\x00\x00\x00\x01\xa0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00\xd0\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x00h\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x004\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x1a\x00\x00\x7f\x00\x00x\x00\x00\x00\x00\x00\r\x00\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x06\x80\x00\x7f\x00\x01\xe0\x00\x00\x00\x00\x00\x03@\x00\x7f\x00\x03\xc0\x00\x00\x00\x00\x00\x01\xa0\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00\xa0\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00\xa0\x00\x7f\x00\x03\x81\xf0\xff\xc3\xf0?\xc0\xa0\x00\x7f\x00\x03\x83\xfd\xff\xe7\xf8\x7f\xf0\xa0\x00\x7f\x00\x03\x87\xff\xff\xef\xfc\x7f\xf8\xa0\x00\x7f\x00\x03\x8f\x1e\x1f\x0e\x1cp8\xa0\x00\x7f\x00\x03\x8e\x08\x0e\x1c\x0ep\x1c\xa0\x00\x7f\x00\x03\x8e\x00\x0e\x1c\x0ep\x1c\xa0\x00\x7f\x00\x03\x87\x00\x0e8\x06p\x1c\xa0\x00\x7f\x00\x03\x87\xc0\x0e8\x07p8\xa0\x00\x7f\x00\x03\x83\xf0\x0e8\x07xx\xa0\x00\x7f\x00\x03\x81\xfc\x0e8\x07\x7f\xf0\xa0\x00\x7f\x00\x03\x80~\x0e8\x07\x7f\xe0\xa0\x00\x7f\x00\x03\x80\x1e\x0e8\x07x\x00\xa0\x00\x7f\x00\x03\x80\x0e\x0e8\x07x\x00\xa0\x00\x7f\x00\x03\x80\x07\x0e\x1c\x0ex\x00\xa0\x00\x7f\x00\x03\x80\x07\x0e\x1c\x0ex\x00\xa0\x00\x7f\x00\x03\x8e\x0e\x0e\x1e\x1ex\x00\xa0\x00\x7f\x00\x03\x8f\xfe\x0e\x0f\x00\x00\x00\x00\x7f\x00\x00\x00\x00>>\x1d\x00\x00\x00\x00\x7f\x00\x00\x00\x00<{\x0f\x00\x00\x00\x00\x7f\x00\x00\x00\x00|y\x0e\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\xfe\x87\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\xfe\x87\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\xff\x83\xa0\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\xfe\x83\xe0\x00\x00\x00\x7f\x00\x00\x00\x03\xe0\xff\x81\xd0\x00\x00\x00\x7f\x00\x00\x00\x03\xc0\xff\x80\xf0\x00\x00\x00\x7f\x00\x00\x00\x07\xc0\x7f\x00\xe8\x00\x00\x00\x7f\x00\x00\x00\x0f\x80\x7f\x00|\x00\x00\x00\x7f\x00\x00\x00\x0f\x80\x7f\x00t\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x7f\x00>\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x7f\x00>\x00\x00\x00\x7f\x00\x00\x00>\x00\x7f\x00\x1d\x00\x00\x00\x7f\x00\x00\x00>\x00\x7f\x00\x1f\x00\x00\x00\x7f\x00\x00\x00|\x00\x7f\x00\x0e\x80\x00\x00\x7f\x00\x00\x00\xf8\x00\x7f\x00\x07\xc0\x00\x00\x7f\x00\x00\x00\xf8\x00\x7f\x00\x07@\x00\x00\x7f\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x7f\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x7f\x00\x00\x03\xe0\x00>\x00\x01\xd0\x00\x00\x7f\x00\x00\x03\xe0\x00>\x00\x01\xf0\x00\x00\x7f\x00\x00\x07\xc0\x00>\x00\x00\xe8\x00\x00\x7f\x00\x00\x0f\xc0\x00>\x00\x00\xfc\x00\x00\x7f\x00\x00\x0f\x80\x00\x1c\x00\x00t\x00\x00\x7f\x00\x00\x1f\x00\x00\x00\x00\x00>\x00\x00\x7f\x00\x00\x1f\x00\x00\x00\x00\x00:\x00\x00\x7f\x00\x00>\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00>\x00\x00>\x00\x00\x1f\x00\x00\x7f\x00\x00|\x00\x00}\x00\x00\x0e\x80\x00\x7f\x00\x00\xfc\x00\x00~\x80\x00\x0f\xc0\x00\x7f\x00\x00\xf8\x00\x00\x7f\x80\x00\x07@\x00\x7f\x00\x01\xf8\x00\x00\x7f\x80\x00\x07\xe0\x00\x7f\x00\x01\xf0\x00\x00\x7f\x00\x00\x03\xa0\x00\x7f\x00\x03\xe0\x00\x00?\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x1e\x00\x00\x01\xf0\x00\x7f\x00\x07\xc0\x00\x00\x00\x00\x00\x00\xe8\x00\x7f\x00\x0f\xc0\x00\x00\x00\x00\x00\x00\xfc\x00\x7f\x00\x0f\x80\x00\x00\x00\x00\x00\x00\xf4\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +YES=Accept +NO=Decline diff --git a/mixly/boards/default_src/micropython/origin/build/lib/irremote.py b/mixly/boards/default_src/micropython/origin/build/lib/irremote.py new file mode 100644 index 00000000..756844ea --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/irremote.py @@ -0,0 +1,259 @@ +""" +IR-Remote + +Micropython library for the IR-Remote/Timer(IR_RX&TX) +=============================================== +@dahanzimin From the Mixly Team +""" +import array, time, gc +from machine import Pin, Timer +from os import uname +try: + from esp32 import RMT + TX_MOED = 1 +except: + from machine import PWM + TX_MOED = 0 + +'''接收部分''' +class IR_RX: + BADSTART = 'Invalid start pulse' + BADDATA = 'Invalid data' + def __init__(self, pin, callback=None, timeout=15000, timer_id=1): + self._start = 0 + self._ready = False + self._enable = False + self._timeout = timeout + self._callback = callback + self._pulses = array.array('H') + self.code = [None, None, None, memoryview(self._pulses)] #存放[cmd, addr, data, pulses] + Pin(pin, Pin.IN).irq(handler=self._irq_cb, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING)) + Timer(0 if "-C2" in uname().machine else timer_id).init(period=5, mode=Timer.PERIODIC, callback=self._timer_cb) + + def _irq_cb(self, pin): + if not self._enable: + _intime = time.ticks_us() + if self._start == 0: + self._start = _intime + return + self._pulses.append(time.ticks_diff(_intime, self._start)) + self._start = _intime + else: + self._start = 0 + self._pulses = array.array('H') + + def _timer_cb(self, tim): + if len(self._pulses) >= 3 and time.ticks_diff(time.ticks_us(), self._start) > self._timeout: + #接收完成,开始解码 + self.code[3] = memoryview(self._pulses) + if self.decode() is None and self._callback: + self._callback(self.code[0], self.code[1], self.code[2], self.code[3]) + self._ready = True + self._start = 0 + self._pulses = array.array('H') + gc.collect() + + def recv_cb(self, callback): + self._callback = callback + + def timeout(self, timeout=15000): + self._timeout = timeout + + def any(self): + ready = self._ready + self._ready = False + return ready + + def enable(self, onoff): + self._enable = onoff + +class NEC_RX(IR_RX): + def __init__(self, pin, bits=None, callback=None, timer_id=1): + super().__init__(pin, callback, timer_id=timer_id) + self._bits = bits + + def decode(self): + pulse_len = len(self._pulses) + if pulse_len < 3: + print("Warning:", self.BADSTART) + return False + else: + start_i = 0 + value = 0 + #跳过帧头(各厂家定义不一) + for i in range(pulse_len): + if self._pulses[i] <= 2250: + start_i = i + break + val = 1 << ((pulse_len - start_i - 1) // 2) - 1 if (pulse_len - start_i) >= 3 else 0 + #根据高低脉冲定义转码 + for edge in range(start_i, pulse_len - 1, 2): + value >>= 1 + if self._pulses[edge + 1] > 1120: + value |= val + #判读是8、16位解码 + if self._bits == 8 or self._bits == 16: + cmd = value >> 16 & 0xff + if cmd != (value >> 24 ^ 0xff) and value != 0x0: + print("Warning:", self.BADDATA) + return False + addr = value & 0xff if self._bits == 8 else value & 0xffff + self.code[0:3] = cmd, addr, value + #其他未定义直接输出转码 + else: + self.code[0:3] = None, None, value + +class RC5_RX(IR_RX): + def __init__(self, pin, callback=None, timer_id=1): + super().__init__(pin, callback, timer_id=timer_id) + + def decode(self): + pulse_len = len(self._pulses) + if pulse_len < 3: + print("Warning:", self.BADSTART) + return False + else: + bit = 1 + value = 0 + num = 0 + while True: + short = self._pulses[num] < 1334 + if not short: + bit ^= 1 + value <<= 1 + value |= bit + num += 1 + int(short) + if num >= pulse_len: + value >>= 1 + break + #判读解码 + cmd = (value & 0x3f) | (0 if ((value >> 12) & 1) else 0x40) + addr = (value >> 6) & 0x1f + self.code[0:3] = cmd, addr, value + +'''发射部分''' +class IR_TX: + def __init__(self, pin, cfreq=38000, power=60): + if TX_MOED: + self._rmt = RMT(0, pin=Pin(pin), clock_div=80, tx_carrier = (cfreq, round(power * 0.75), 1)) + else: + self._pwm = PWM(Pin(pin), freq=cfreq, duty_u16=0) + self._duty = round(power * 65535 / 100 * 0.75) + self._busy = False + self._pulses = array.array('H') + self.carrier = False + + def _pwm_write_pulses(self, pulses): + _flip = True + self._busy = True + for pulse in pulses: + if _flip: + self._pwm.duty_u16(self._duty) + time.sleep_us(pulse) + _flip = False + else: + self._pwm.duty_u16(0) + time.sleep_us(pulse) + _flip = True + self._pwm.duty_u16(0) + self._busy = False + + def transmit(self, cmd=None, addr=None, toggle=None, pulses=None, raw=None): + if pulses is None: + self.carrier = False + if raw is None: + self.tx(cmd, addr, toggle) + else: + self.tx_raw(raw) + if TX_MOED: + self._rmt.write_pulses(tuple(self._pulses)) + else: + self._pwm_write_pulses(tuple(self._pulses)) + self._pulses = array.array('H') + else: + if TX_MOED: + self._rmt.write_pulses(tuple(pulses)) + else: + self._pwm_write_pulses(tuple(pulses)) + + def busy(self): + return not self._rmt.wait_done() if TX_MOED else self._busy + + def _append(self, *times): + for t in times: + self._pulses.append(t) + self.carrier = not self.carrier + + def _add(self, t): + assert t > 0 + self._pulses[len(self._pulses)-1] +=t + +class NEC_TX(IR_TX): + _TBURST = const(563) + _T_ONE = const(1687) + def __init__(self, pin, samsung=False, power=60): + super().__init__(pin, 38000, power) + self._samsung = samsung + + def _bit(self, b): + self._append(_TBURST, _T_ONE if b else _TBURST) + + def tx(self, cmd, addr, toggle=0): #cmd:0~0xff, addr:0~0xffff, toggle:0,1 + if self._samsung: + self._append(4500, 4500) + else: + self._append(9000, 4500) + if addr < 256: # Short address: append complement + if self._samsung: + addr |= addr << 8 + else: + addr |= ((addr ^ 0xff) << 8) + for _ in range(16): + self._bit(addr & 1) + addr >>= 1 + cmd |= ((cmd ^ 0xff) << 8) + for _ in range(16): + self._bit(cmd & 1) + cmd >>= 1 + self._append(_TBURST) + if toggle == 1: + self._append(30000, 9000, 2250, _TBURST) + + def tx_raw(self, raw): + self._append(9000, 4500) + while raw: + self._bit(raw & 1) + raw >>= 1 + self._append(_TBURST) + +class RC5_TX(IR_TX): + _T_RC5 = const(889) + def __init__(self, pin, power=60): + super().__init__(pin, 36000, power) + + def tx(self, cmd, addr, toggle): #cmd:0~0x3f, addr:0~0x1f, toggle:0,1 + d = (cmd & 0x3f) | ((addr & 0x1f) << 6) | (((cmd & 0x40) ^ 0x40) << 6) | ((toggle & 1) << 11) + mask = 0x2000 + while mask: + if mask == 0x2000: + self._append(_T_RC5) + else: + bit = bool(d & mask) + if bit ^ self.carrier: + self._add(_T_RC5) + self._append(_T_RC5) + else: + self._append(_T_RC5, _T_RC5) + mask >>= 1 + + def tx_raw(self, raw): + self._append(_T_RC5) + mask = 1 << len(bin(raw)) - 3 + while mask: + if bool(raw & mask) ^ self.carrier: + self._add(_T_RC5) + self._append(_T_RC5) + else: + self._append(_T_RC5, _T_RC5) + mask >>= 1 + self._append(_T_RC5) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/keypad.py b/mixly/boards/default_src/micropython/origin/build/lib/keypad.py new file mode 100644 index 00000000..f23e9cbe --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/keypad.py @@ -0,0 +1,49 @@ +""" +Simple Keypad + +Micropython library for the Simple Keypad +======================================================= + +#Based on Author: 'Teeraphat Kullanankanjana' +@dahanzimin From the Mixly Team +""" + +from machine import Pin +from time import sleep + +class Keypad: + def __init__(self, row_pins, column_pins, keys): + """Initialize the keypad object.""" + if not all(isinstance(pin, Pin) for pin in row_pins): + raise ValueError("Row pins must be instances of Pin.") + + if not all(isinstance(pin, Pin) for pin in column_pins): + raise ValueError("Column pins must be instances of Pin.") + + if not isinstance(keys, list) or not all(isinstance(row, list) for row in keys): + raise ValueError("Keys must be a 2D list.") + + self.row_pins = row_pins + self.column_pins = column_pins + self.keys = keys + + for pin in self.row_pins: + pin.init(Pin.IN, Pin.PULL_UP) + + for pin in self.column_pins: + pin.init(Pin.OUT) + + if len(self.row_pins) > len(self.keys) or len(self.column_pins) > len(self.keys[0]): + raise ValueError("Number of row/column pins does not match the key layout size.") + + def read_keypad(self): + """Read the keypad and return the pressed key.""" + for col_pin in self.column_pins: + col_pin.value(0) + for i, row_pin in enumerate(self.row_pins): + if not row_pin.value(): + key_pressed = self.keys[i][self.column_pins.index(col_pin)] + col_pin.value(1) + return key_pressed + col_pin.value(1) + return None diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ltr308al.py b/mixly/boards/default_src/micropython/origin/build/lib/ltr308al.py new file mode 100644 index 00000000..2f2fc5fc --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ltr308al.py @@ -0,0 +1,76 @@ +""" +LTR-308ALS + +Micropython library for the LTR-308ALS +======================================================= + +#Changed from circuitpython to micropython 20220211 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +LTR_308ALS_ADDRESS = const(0x53) + +LTR_308ALS_REG_CTRL = const(0x00) +LTR_308ALS_REG_GAIN = const(0x05) #设置增益 +LTR_308ALS_REG_DEVICE_ID = const(0x06) +LTR_308ALS_REG_DATA = const(0x0D) + +#设置增益范围 +LTR_308ALS_CMD_ALS_Enable = const(0x02) +LTR_308ALS_CMD_X1GAIN =const(0x00) +LTR_308ALS_CMD_X3GAIN =const(0x01) +LTR_308ALS_CMD_X6GAIN =const(0x02) +LTR_308ALS_CMD_X9GAIN =const(0x03) +LTR_308ALS_CMD_X18GAIN =const(0x04) + +_GAINS = ( + LTR_308ALS_CMD_X1GAIN, # 1x + LTR_308ALS_CMD_X3GAIN, # 3x + LTR_308ALS_CMD_X6GAIN, # 6x + LTR_308ALS_CMD_X9GAIN, # 9x + LTR_308ALS_CMD_X18GAIN # 18x +) + +_GAINS_X = ( + 1, # 1x + 3, # 3x + 6, # 6x + 9, # 9x + 18 # 18x +) + +class LTR_308ALS: + def __init__(self, i2c_bus,gain=1): + self._device = i2c_bus + self._address = LTR_308ALS_ADDRESS + self._gain = gain + + if self._chip_id() != 0xB1: + raise AttributeError("Cannot find a LTR_308ALS") + self._Enable() #star + time.sleep(0.2) + self._wreg(LTR_308ALS_REG_GAIN,_GAINS[self._gain]) + + #Write memory address + def _wreg(self, reg, val): + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + #Read memory address + def _rreg(self, reg,nbytes=1): + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(LTR_308ALS_REG_DEVICE_ID) + + def _Enable(self): + self._wreg(LTR_308ALS_REG_CTRL,LTR_308ALS_CMD_ALS_Enable) + + def getdata(self): + buffer=self._rreg(LTR_308ALS_REG_DATA,3) + als_data= buffer[2]<<16 | buffer[1]<<8| buffer[0] + als_lux=float(0.6*als_data/_GAINS_X[self._gain]) + return als_lux + diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ltr381rgb.py b/mixly/boards/default_src/micropython/origin/build/lib/ltr381rgb.py new file mode 100644 index 00000000..c285235d --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ltr381rgb.py @@ -0,0 +1,78 @@ +""" +LTR-381RGB-XX + +MicroPython library for the LTR-381RGB-XX (Color sensor) +======================================================= + +#Preliminary composition 20230417 + +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +LTR_MAIN_CTRL = const(0x00) +LTR_ALS_CS_MEAS_RATE = const(0x04) +LTR_ALS_CS_GAIN = const(0x05) +LTR_PART_ID = const(0x06) +LTR_MAIN_STATUS = const(0x07) +LTR_CS_DATA = const(0x0A) + #1x 3x 6x 9x 18x +_GAINS_X = (1, 3, 6, 9, 18) + +class LTR_381RGB: + def __init__(self, i2c_bus, addr=0x53, gain=1): + self._device = i2c_bus + self._address = addr + self._gain = gain + self._color = [0, 0, 0] + self._ir = 0 + self._als = 0 + + if (self._chip_id() & 0xF0) != 0xC0: + raise AttributeError("Cannot find a LTR-381RGB") + + self._configure() + time.sleep(0.1) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + '''Proofreading device ID''' + return self._rreg(LTR_PART_ID) + + def _configure(self): + '''Configuration Register''' + self._wreg(LTR_MAIN_CTRL, 0x06) #CS mode & ALS/CS Enable + self._wreg(LTR_ALS_CS_MEAS_RATE, 0x22) #Resolution = 18 bit, Meas Rate =100ms + self._wreg(LTR_ALS_CS_GAIN, self._gain & 0x07) #CS measurement Gain Range + + def status(self): + '''Data conversion status''' + return self._rreg(LTR_MAIN_STATUS) & 0x08 + + def getdata(self): + '''Processing data acquisition''' + if self.status(): + _buf=self._rreg(LTR_CS_DATA, 12) + self._ir = _buf[2] << 16 | _buf[1] << 8 | _buf[0] + self._color [1] = _buf[5] << 16 | _buf[4] << 8 | _buf[3] + self._color [0] = _buf[8] << 16 | _buf[7] << 8 | _buf[6] + self._color [2] = _buf[11] << 16 | _buf[10] << 8 | _buf[9] + self._als = 0.8 * self._color [1] * (1 - 0.033 * self._ir / self._color [1]) / _GAINS_X[self._gain] + return round(self._als, 2), self._ir, self._color + + def color(self): + return self.getdata()[2] + + def ir(self): + return self.getdata()[1] + + def als(self): + return self.getdata()[0] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ltr390uv.py b/mixly/boards/default_src/micropython/origin/build/lib/ltr390uv.py new file mode 100644 index 00000000..a4ec5727 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ltr390uv.py @@ -0,0 +1,75 @@ +""" +LTR-390UV + +Micropython library for the LTR-390UV(ALS+UV) +======================================================= + +#Preliminary composition 20240120 + +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_LTR390_ADDRESS = const(0x53) +_LTR390_REG_CTRL = const(0x00) +_LTR390_REG_MEAS = const(0x04) +_LTR390_REG_GAIN = const(0x05) +_LTR390_REG_ID = const(0x06) +_LTR390_REG_ALS = const(0x0D) +_LTR390_REG_UVS = const(0x10) + +_RATE_DEFAULT = const(0x02) #100ms +_RESOLUTION_20BIT = (0<<4, 4) +_RESOLUTION_19BIT = (1<<4, 2) +_RESOLUTION_18BIT = (2<<4, 1) +_RESOLUTION_17BIT = (3<<4, 0.5) +_RESOLUTION_16BIT = (4<<4, 0.25) +_RESOLUTION_13BIT = (5<<4, 0.125) + +_GAIN_X1 = (0, 1) +_GAIN_X3 = (1, 3) +_GAIN_X6 = (2, 6) +_GAIN_X9 = (3, 9) +_GAIN_X18 = (4, 18) + +class ALS_UVS: + def __init__(self, i2c_bus, addr=_LTR390_ADDRESS, gain=_GAIN_X1, resolution=_RESOLUTION_17BIT): + self._device = i2c_bus + self._address = addr + self._gain = gain + self._reso = resolution + self._flaga = False + self._flagu = False + + if self._rreg(_LTR390_REG_ID) != 0xB2: + raise AttributeError("Cannot find a LTR-390UV") + + self._wreg(_LTR390_REG_MEAS, self._reso[0] | _RATE_DEFAULT) + self._wreg(_LTR390_REG_GAIN, self._gain[0]) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def ultraviolet(self): + if not self._flagu: + self._wreg(_LTR390_REG_CTRL, 0x0A) #UVS in Active Mode + time.sleep_ms(int(self._reso[1] * 100)) + self._flagu = True + self._flaga = False + buf = self._rreg(_LTR390_REG_UVS, 3) + return buf[2] << 16 | buf[1] << 8 | buf[0] + + def ambient_light(self): + if not self._flaga: + self._wreg(_LTR390_REG_CTRL, 0x02) #ALS in Active Mode + time.sleep_ms(int(self._reso[1] * 100)) + self._flaga = True + self._flagu = False + buf = self._rreg(_LTR390_REG_ALS, 3) + return 0.6 * (buf[2] << 16 | buf[1] << 8 | buf[0]) / (self._gain[1] * self._reso[1]) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ltr553als.py b/mixly/boards/default_src/micropython/origin/build/lib/ltr553als.py new file mode 100644 index 00000000..e3397b3c --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ltr553als.py @@ -0,0 +1,106 @@ +""" +LTR-553ALS-XX + +MicroPython library for the LTR-553ALS-XX(ALS,PS) +======================================================= + +#Preliminary composition 20220224 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +LTR_553ALS_ADDRESS = const(0x23) +LTR_ALS_REG_CONTR = const(0x80) +LTR_PS_REG_CONTR = const(0x81) +LTR_PS_REG_LED = const(0x82) +LTR_PS_REG_PULSES = const(0x83) +LTR_PS_REG_RATE = const(0x84) +LTR_ALS_REG_RATE = const(0x85) +LTR_553ALS_REG_ID = const(0x87) +LTR_ALS_REG_DATA1 = const(0x88) +LTR_553ALS_REG_ATATUS = const(0x8C) +LTR_PS_REG_DATA1 = const(0x8D) + +_ALS_GAIN={ + "X1":(1,0x01), # For Gain X1 + "X2":(2,0x05), # For Gain X2 + "X4":(4,0x09), # For Gain X4 + "X8":(8,0x0D), # For Gain X8 + "X48":(48,0x19), # For Gain X48 + "X96":(96,0x1D), # For Gain X96 +} + +class LTR_553ALS: + + def __init__(self, i2c_bus,addr=LTR_553ALS_ADDRESS,ALS_Gain="X1"): + self._device = i2c_bus + self._address = addr + self.ALS_IR = 0 + self.ALS_VIS = 0 + self.PS = 0 + self.ALS_gain = ALS_Gain + + if self._chip_id() != 0x05: + raise AttributeError("Cannot find a LTR_553ALS") + + self._configure() + #time.sleep(0.1) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + '''校对设备ID''' + return self._rreg(LTR_553ALS_REG_ID) + + def _configure(self): + '''配置寄存器''' + self._wreg(LTR_ALS_REG_CONTR,_ALS_GAIN[self.ALS_gain][1]) # ALS_CONTR: Active mode + self._wreg(LTR_PS_REG_CONTR,0x03) # PS_CONTR: Active mode + self._wreg(LTR_PS_REG_LED,0x5B) #PS_LED: LED_pulse_period=50khz,DUTY = 100%,LED_pulsed_current_level = 50mA + self._wreg(LTR_PS_REG_PULSES,0x0A) #PS_N_Pulses: Number_of_pulses = 10 + self._wreg(LTR_PS_REG_RATE,0x08) #PS_Measurement_Rate=10ms + self._wreg(LTR_ALS_REG_RATE,0x12) #ALS_Measurement_Rate=200ms,ALS_integration_time=200ms + + def _status(self): + '''数据转换状态''' + status=self._rreg(LTR_553ALS_REG_ATATUS) + return status&0x84, status&0x01 #ALS,PS status + + @property + def getdata(self): + '''处理获取数据''' + if self._status()[0]: + data_als=self._rreg(LTR_ALS_REG_DATA1,4) + als_ch1=data_als[0] | data_als[1]<<8 + als_ch0=data_als[2] | data_als[3]<<8 + ratio=als_ch1/(als_ch1+als_ch0) if (als_ch1+als_ch0)>0 else 0 + self.ALS_IR =als_ch1*ratio/_ALS_GAIN[self.ALS_gain][0] + self.ALS_VIS=als_ch0*ratio/_ALS_GAIN[self.ALS_gain][0] + + if self._status()[1]: + data_ps=self._rreg(LTR_PS_REG_DATA1,2) + self.PS =data_ps[0] | data_ps[1]<<8 + + return round(self.ALS_VIS,2),round(self.ALS_IR,2),self.PS + + def als_vis(self): + '''可见光Lux''' + return self.getdata[0] + + def als_ir(self): + '''红外Lux''' + return self.getdata[1] + + def ps_nl(self): + '''接近距离''' + return self.getdata[2] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/matcher.py b/mixly/boards/default_src/micropython/origin/build/lib/matcher.py new file mode 100644 index 00000000..5d641ccb --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/matcher.py @@ -0,0 +1,97 @@ +# SPDX-FileCopyrightText: 2017 Yoch +# +# SPDX-License-Identifier: EPL-1.0 + +""" +`matcher` +==================================================================================== + +MQTT topic filter matcher from the Eclipse Project's Paho.MQTT.Python +https://github.com/eclipse/paho.mqtt.python/blob/master/src/paho/mqtt/matcher.py +* Author(s): Yoch (https://github.com/yoch) +""" + + +class MQTTMatcher: + """Intended to manage topic filters including wildcards. + + Internally, MQTTMatcher use a prefix tree (trie) to store + values associated with filters, and has an iter_match() + method to iterate efficiently over all filters that match + some topic name. + """ + + # pylint: disable=too-few-public-methods + class Node: + """Individual node on the MQTT prefix tree.""" + + __slots__ = "children", "content" + + def __init__(self): + self.children = {} + self.content = None + + def __init__(self): + self._root = self.Node() + + def __setitem__(self, key, value): + """Add a topic filter :key to the prefix tree + and associate it to :value""" + node = self._root + for sym in key.split("/"): + node = node.children.setdefault(sym, self.Node()) + node.content = value + + def __getitem__(self, key): + """Retrieve the value associated with some topic filter :key""" + try: + node = self._root + for sym in key.split("/"): + node = node.children[sym] + if node.content is None: + raise KeyError(key) + return node.content + except KeyError: + raise KeyError(key) from None + + def __delitem__(self, key): + """Delete the value associated with some topic filter :key""" + lst = [] + try: + parent, node = None, self._root + for k in key.split("/"): + parent, node = node, node.children[k] + lst.append((parent, k, node)) + node.content = None + except KeyError: + raise KeyError(key) from None + else: # cleanup + for parent, k, node in reversed(lst): + if node.children or node.content is not None: + break + del parent.children[k] + + def iter_match(self, topic): + """Return an iterator on all values associated with filters + that match the :topic""" + lst = topic.split("/") + normal = not topic.startswith("$") + + def rec(node, i=0): + if i == len(lst): + if node.content is not None: + yield node.content + else: + part = lst[i] + if part in node.children: + for content in rec(node.children[part], i + 1): + yield content + if "+" in node.children and (normal or i > 0): + for content in rec(node.children["+"], i + 1): + yield content + if "#" in node.children and (normal or i > 0): + content = node.children["#"].content + if content is not None: + yield content + + return rec(self._root) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/matrix16x8.py b/mixly/boards/default_src/micropython/origin/build/lib/matrix16x8.py new file mode 100644 index 00000000..195a49bd --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/matrix16x8.py @@ -0,0 +1,71 @@ +""" +Matrix16x8 Displays + +Micropython library for the HT16K33 Matrix16x8 Displays +======================================================= + +#Preliminary composition 20230411 + +dahanzimin From the Mixly Team +""" +from ht16k33 import HT16K33 + +class Matrix(HT16K33): + """A single matrix.""" + def __init__(self, i2c, address=0x70, brightness=0.3, font="5x8", font_address=0x3A0000, width=16, height=8): + super().__init__(i2c, address, brightness, width, height) + self.font(font) + self.uin_font(font_address) + + """Graph module""" + HEART=b' \x02p\x07\xf8\x0f\xf8\x0f\xf0\x07\xe0\x03\xc0\x01\x80\x00' + HEART_SMALL=b'\x00\x00 \x02p\x07\xf0\x07\xe0\x03\xc0\x01\x80\x00\x00\x00' + HAPPY=b'\x00\x00\x00\x00\x18\x18\x18\x18\x00\x00 \x04@\x02\x80\x01' + SAD=b'\x00\x00\x00\x008\x1c\x04 \x00\x00\x80\x01@\x02 \x04' + SMILE=b'\x00\x00\x18\x18$$\x00\x00\x00\x00 \x04@\x02\x80\x01' + SILLY=b'\x00\x00\x18\x18$$\x18\x18\x00\x00\xc0\x03@\x02\x80\x01' + FABULOUS=b'8\x1cD"|>\x00\x00\x00\x00\xe0\x07 \x04\xc0\x03' + SURPRISED=b'\x00\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x00\x00\x80\x00' + ASLEEP=b'\x00\x00\x00\x00<<\x00\x00\x00\x00\xc0\x03 \x04\xc0\x03' + ANGRY=b'D"(\x14\x10\x08\x00\x00\x80\x01@\x02 \x04\x10\x08' + CONFUSED=b'\x00\x00\xc0\x01 \x02\x00\x02\x00\x01\x80\x00\x00\x00\x80\x00' + NO=b'\x00\x00\x10\x02 \x01\xc0\x00\xc0\x00 \x01\x10\x02\x00\x00' + YES=b'\x00\x00\x00\x10\x00\x08\x00\x04\x10\x02 \x01\xc0\x00\x00\x00' + LEFT_ARROW=b'\x00\x00 \x00\x10\x00\x08\x00\xf4?\x08\x00\x10\x00 \x00' + RIGHT_ARROW=b'\x00\x00\x00\x04\x00\x08\x00\x10\xfc/\x00\x10\x00\x08\x00\x04' + DRESS=b' \x02\xf0\x07`\x03\xc0\x01\xa0\x02P\x05\xa8\n\xf0\x07' + TRANSFORMERS=b'\x00\x00\x80\x00`\x03\xa0\x02\xa0\x02@\x01@\x01 \x02' + SCISSORS=b' \x08`\x0c\xc0\x06\x80\x03\x00\x01\xc0\x06\xa0\n@\x04' + EXIT=b'\x00\x0c\x00\x07\x80\x0e@2\x00\x05@\t\x00\x11\x00 ' + TREE=b'\x80\x00\xc0\x01\xe0\x03\xf0\x07\xf8\x0f\x80\x00\x80\x00\x80\x00' + PACMAN=b'\xf0\x03\x18\x04L\x02\x04\x01\x0c\x02\x18\x04\xf0\x03\x00\x00' + TARGET=b'\x00\x00\x00\x00\x80\x03@\x04@\x05@\x04\x80\x03\x00\x00' + TSHIRT=b' \x04\xd0\x0b\x08\x100\x0c \x04 \x04 \x04\xe0\x07' + ROLLERSKATE=b'\xf0\x00\x90\x00\x90\x07\x10\x08\xf0\x0f(\x148\x1c\x00\x00' + DUCK=b'\xe0\x00\x90\x01\x08\x01<\x01 \x7f \x10\xe0\x0f' + HOUSE=b"\xfc?\x06`\x03\xc0\xe4'$$\xa4$$$$$" + TORTOISE=b'\x80\x01\xa0\x05\xe0\x07\xe0\x07\xe0\x07\xc0\x03 \x04\x00\x00' + BUTTERFLY=b'\x00\x00`\x0c\x90\x12\xe0\x0f\x80\x03@\x05\xa0\n`\x0c' + STICKFIGURE=b'\x80\x00@\x01\x80\x00\xc0\x01\xa0\x02\x80\x00@\x01 \x02' + GHOST=b'\xe0\x03\xb0\x06\xb0\x06\xf0\x07\xb0\x06P\x05\xf0\x0f\xf0\x1f' + PITCHFORK=b'\x00\xf8\x00\x04\x00\x04\xff\xff\x00\x04\x00\x04\x00\xf8\x00\x00' + MUSIC_QUAVERS=b'\x00\x00\x00\x00\x18\x86\x00\x1c' + MUSIC_CROTCHET=b'\x00\x00\xff\x0f\x00\x1e\x00?\x00?\x00>\x00\x1c\x00\x00' + COW=b'\x08\x00\x1e\x00\xfa\x07\xfe\x0f\xfe70F0\x060\x06' + RABBIT=b'\xc0?~@\x01Q>\\\x01Q~@\xc0?\x00\x00' + SQUARE_SMALL=b'\x00\x00\x00\x00\xc0\x03@\x02@\x02\xc0\x03\x00\x00\x00\x00' + SQUARE=b'\xf0\x0f\x10\x08\x10\x08\x10\x08\x10\x08\x10\x08\x10\x08\xf0\x0f' + DIAMOND_SMALL=b'\x00\x00\x00\x00\xc0\x01\xa0\x02@\x01\x80\x00\x00\x00\x00\x00' + DIAMOND=b'\xf0\x07X\r\xec\x1b\xd8\r\xb0\x06`\x03\xc0\x01\x80\x00' + CHESSBOARD=b'\x00\x00\xf8?\xa8*\xf8?\xa8*\xf8?\xa8*\xf8?' + TRIANGLE_LEFT=b'\x00\x00\x00\x01\x80\x01\xc0\x01\xe0\x01\xc0\x01\x80\x01\x00\x01' + TRIANGLE=b'\x00\x00\x80\x01\xc0\x03\xe0\x07\xf0\x0f\xf8\x1f\xfc?\x00\x00' + SNAKE=b'\x00\x0e\x00\n\x00\x0e\xf0\x03\xf8\x03\x1c\x00\x0e\x00\x00\x00' + UMBRELLA=b'\x80\x00\xe0\x03\xf0\x07\xf8\x0f\x80\x00\x80\x00\x80\x02\x80\x03' + SKULL=b'\xe0\x03\x90\x04\x88\x08x\x0f\xf0\x07 \x02\xa0\x02\xc0\x01' + GIRAFFE=b'\x80\x01\x80\x03\x80\x00\x80\x00\x80\x00\xf0\x00\x90\x00\x90\x00' + SWORD=b'\x00\x00\x10\x000\x00\xfc\x1f\xfc\x1f0\x00\x10\x00\x00\x00' + DOOR_OPENING=b'\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff' + DOOR_OPEN=b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff' + DOOR_CLOSE=b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' diff --git a/mixly/boards/default_src/micropython/origin/build/lib/matrix32x12.py b/mixly/boards/default_src/micropython/origin/build/lib/matrix32x12.py new file mode 100644 index 00000000..d4ad13c7 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/matrix32x12.py @@ -0,0 +1,70 @@ +""" +Matrix Displays + +Micropython library for the TM1680 Matrix Displays +======================================================= + +#Preliminary composition 20230414 + +dahanzimin From the Mixly Team +""" +from tm1680 import TM1680 + +class Matrix(TM1680): + """A single matrix.""" + def __init__(self, i2c, address=0x72, brightness=0.3, font_address=0x3A0000, width=32, height=12): + super().__init__(i2c, address, brightness, width, height) + self.font(font_address) + + """Graph module""" + HEART_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x02\x00\x00p\x07\x00\x00\xf8\x0f\x00\x00\xf8\x0f\x00\x00\xf0\x07\x00\x00\xe0\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + HEART=b'\x00\x00\x00\x00\x00 \x02\x00\x00p\x07\x00\x00\xf8\x0f\x00\x00\xfc\x1f\x00\x00\xfc\x1f\x00\x00\xf8\x0f\x00\x00\xf0\x07\x00\x00\xe0\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00' + HAPPY=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x08\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x00\x00\x00' + SAD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x00\x00\x00' + SMILE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c0\x00\x008\x1c\x00\x00\xe0\x07\x00\x00\x00\x00\x00' + SILLY=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x08\x10\x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x07\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x00\x00\x00' + FABULOUS=b'\x00\x00\x00\x00\x00\x04 \x00\x00\x08\x10\x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x1f\x00\x00\x08\x10\x00\x00\x08\x10\x00\x00\x10\x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00' + SURPRISED=b'\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00' + ASLEEP=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x07\x00\x00\x10\x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00' + ANGRY=b'\x00\x00\x00\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x08\x10\x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x08\x10\x00' + CONFUSED=b'\x00\xc0\x03\x00\x00`\x06\x00\x000\x0c\x00\x000\x0c\x00\x00\x00\x0c\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x80\x01\x00' + NO=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x08\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00' + YES=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x18\x00\x00\x00\x0c\x00\x00\x00\x06\x00\x00\x0c\x03\x00\x00\x98\x01\x00\x00\xf0\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + LEFT_ARROW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00 \x00\x00\x00\x10\x00\x00\x00\xe8\x1f\x00\x00\x10\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + RIGHT_ARROW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\xf8\x17\x00\x00\x00\x08\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DRESS=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x02\x00\x00\xf0\x07\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00P\x05\x00\x00\xa8\n\x00\x00\xf0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TRANSFORMERS=b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xc0\x06\x00\x00@\x05\x00\x00@\x05\x00\x00@\x05\x00\x00\x80\x02\x00\x00\x80\x02\x00\x00@\x04\x00\x00 \x08\x00\x00\x00\x00\x00' + SCISSORS=b'\x00\x00\x00\x00\x00\x04\x10\x00\x00\x0c\x18\x00\x00\x18\x0c\x00\x000\x06\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00p\x07\x00\x00H\t\x00\x00H\t\x00\x000\x06\x00' + EXIT=b'\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\xc0\x01\x00\x00\xa0\x03\x00\x00\x90\x0c\x00\x00\x80\x00\x00\x00P\x01\x00\x00@\x02\x00\x00@\x04\x00\x00\x00\x08\x00\x00\x00\x00\x00' + TREE=b'\x00\x00\x00\x00\x00\x80\x00\x00\x00\xc0\x01\x00\x00\xe0\x03\x00\x00\xf0\x07\x00\x00\xf8\x0f\x00\x00\xfc\x1f\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00' + PACMAN=b'\x00\x00\x00\x00\x00\xf0\x07\x00\x00\x18\x08\x00\x00\x8c\x04\x00\x00\x0c\x02\x00\x00\x04\x01\x00\x00\x0c\x02\x00\x00\x0c\x04\x00\x00\x18\x08\x00\x00\xf0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TARGET=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x07\x00\x00 \x08\x00\x00 \x08\x00\x00 \t\x00\x00 \x08\x00\x00 \x08\x00\x00\xc0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TSHIRT=b'\x00@\x04\x00\x00\xa0\x0b\x00\x00\x10\x10\x00\x00\x08 \x00\x000\x18\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00\xe0\x0f\x00\x00\x00\x00\x00' + ROLLERSKATE=b'\x00\x00\x00\x00\x00\xf8\x00\x00\x00\x88\x00\x00\x00\x88\x00\x00\x00\x88\x0f\x00\x00\x08\x10\x00\x00\x08\x10\x00\x00\xf8\x1f\x00\x00\x14(\x00\x00\x1c8\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DUCK=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x90\x00\x00\x00\x08\x01\x00\x00<\x01\x00\x00 ?\x00\x00 \x10\x00\x00 \x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00' + HOUSE=b'\x00\x00\x00\x00\x00\xf0\x0f\x00\x00\x18\x18\x00\x00\x0c0\x00\x00\xd0\x0b\x00\x00P\n\x00\x00P\n\x00\x00\xd0\n\x00\x00P\n\x00\x00P\n\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TORTOISE=b'\x00\x00\x00\x00\x00\x80\x01\x00\x00\xa0\x05\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xc0\x03\x00\x00 \x04\x00\x00\x00\x00\x00' + BUTTERFLY=b'\x00\x00\x00\x00\x00\x18\x0c\x00\x00$\x12\x00\x00D\x11\x00\x00\xf8\x0f\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00\xd0\x05\x00\x00(\n\x00\x00\x18\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00' + STICKFIGURE=b'\x00\x80\x00\x00\x00@\x01\x00\x00@\x01\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00\x90\x04\x00\x00@\x01\x00\x00 \x02\x00\x00\x10\x04\x00\x00\x00\x00\x00' + GHOST=b'\x00\x00\x00\x00\x00\xe0\x03\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00\xf0\x07\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00P\x05\x00\x00\xf0\x0f\x00\x00\xf0\x1f\x00\x00\x00\x00\x00' + PITCHFORK=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\xfc?\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + MUSIC_QUAVERS=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x06\x00\x00x\x0f\x00\x00\xe4=\x00\x00\xc0\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + MUSIC_QUAVER=b'\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00`\x01\x00\x00\xf0\x01\x00\x00\xf8\x01\x00\x00\xf8\x00\x00\x00p\x00\x00' + MUSIC_CROTCHET=b'\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00`\x01\x00\x00\xf0\x01\x00\x00\xf8\x01\x00\x00\xf8\x00\x00\x00p\x00\x00' + COW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00x\x00\x00\x00\xe8\x0f\x00\x00\xf8\x1f\x00\x00\xf8/\x00\x00`,\x00\x00`\x0c\x00\x00`\x0c\x00\x00`\x0c\x00\x00\x00\x00\x00' + RABBIT=b'\x00@\x01\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x000\x06\x00\x00\x10\x04\x00\x00P\x05\x00\x00\x10\x04\x00\x00\x90\x04\x00\x00\xd0\x05\x00\x00\xe0\x03\x00' + SQUARE_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x03\x00\x00@\x02\x00\x00@\x02\x00\x00\xc0\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + SQUARE=b'\x00\xfc?\x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\xfc?\x00' + DIAMOND_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00@\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DIAMOND=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x07\x00\x00X\r\x00\x00\xec\x1b\x00\x00\xd8\r\x00\x00\xb0\x06\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + CHESSBOARD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TRIANGLE_LEFT=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x80\x03\x00\x00\xc0\x03\x00\x00\x80\x03\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + TRIANGLE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xe0\x07\x00\x00\xf0\x0f\x00\x00\xf8\x1f\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + SNAKE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00(\x00\x00\x008\x00\x00\xc0\x0f\x00\x00\xe0\x0f\x00\x00p\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + UMBRELLA=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\xe0\x03\x00\x00\xf0\x07\x00\x00\xf8\x0f\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00' + SKULL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x03\x00\x00\x90\x04\x00\x00\x88\x08\x00\x00x\x0f\x00\x00\xf0\x07\x00\x00 \x02\x00\x00 \x02\x00\x00\xa0\x02\x00\x00\xc0\x01\x00\x00\x00\x00\x00' + GIRAFFE=b'\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xe0\x01\x00\x00 \x01\x00\x00 \x01\x00\x00 \x01\x00' + SWORD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x000\x00\x00\x00\xfc\x1f\x00\x00\xfc\x1f\x00\x000\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + DOOR_OPEN=b'\x00\xf8\x1f\x00\x00\x04 \x00\x00\x0c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00' + DOOR_OPENING=b'\x00\xf8\x1f\x00\x004 \x00\x00L \x00\x00\x8c \x00\x00\x0c!\x00\x00\x0c!\x00\x00L!\x00\x00L!\x00\x00\x0c!\x00\x00\x0c!\x00\x00\x0c!\x00\x00\x0c!\x00' + DOOR_CLOSE=b'\x00\xf8\x1f\x00\x00\xf4/\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c6\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00' diff --git a/mixly/boards/default_src/micropython/origin/build/lib/matrix8x5.py b/mixly/boards/default_src/micropython/origin/build/lib/matrix8x5.py new file mode 100644 index 00000000..d03ae7c9 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/matrix8x5.py @@ -0,0 +1,67 @@ +""" +Matrix8x5 Displays + +Micropython library for the TM1652 Matrix8x5 Displays +======================================================= + +#Preliminary compositio 20230411 + +dahanzimin From the Mixly Team +""" +from tm1652 import TM1652 + +class Matrix(TM1652): + """A single matrix.""" + def __init__(self, pin, brightness=0.3, font="4x5", width=8, height=5): + super().__init__(pin, brightness, width, height) + self.font(font) + + """Graph module 5x8""" + HEART = b'\x14>>\x1c\x08' + HEART_SMALL = b'\x00\x14\x1c\x08\x00' + HAPPY = b'\x00\x14\x00"\x1c' + SAD = b'\x00\x14\x00\x1c"' + SMILE = b'\x00\x14\x00"\x1c' + SILLY = b'"\x00>(8' + FABULOUS = b'>6\x00\x14\x1c' + SURPRISED = b'\x14\x00\x08\x14\x08' + ASLEEP = b'\x006\x00\x1c\x00' + ANGRY = b'"\x14\x00>*' + CONFUSED = b'\x00\x14\x00\x14*' + NO = b'"\x14\x08\x14"' + YES = b'\x00 \x10\n\x04' + LEFT_ARROW = b'\x08\x04~\x04\x08' + RIGHT_ARROW = b'\x10 ~ \x10' + DRESS = b'$f\x08\x08' + PACMAN = b'<\x16\x0e\x1e<' + TARGET = b'\x08\x1c6\x1c\x08' + TSHIRT = b'6>\x1c\x1c\x1c' + ROLLERSKATE = b'00>>\x14' + DUCK = b'\x0c\x0e<\x1c\x00' + HOUSE = b'\x08\x1c>\x1c\x14' + TORTOISE = b'\x00\x1c>\x14\x00' + BUTTERFLY = b'6>\x08>6' + STICKFIGURE = b'\x08>\x08\x14"' + GHOST = b'>*>>*' + PITCHFORK = b'**>\x08\x08' + MUSIC_QUAVERS = b'<$$66' + MUSIC_QUAVER = b'\x08\x18(\x0e\x0e' + MUSIC_CROTCHET = b'\x08\x08\x08\x0e\x0e' + COW = b'"">\x1c\x08' + RABBIT = b'\n\n\x1e\x16\x1e' + SQUARE_SMALL = b'\x00\x1c\x14\x1c\x00' + SQUARE = b'>""">' + DIAMOND_SMALL = b'\x00\x08\x14\x08\x00' + DIAMOND = b'\x08\x14"\x14\x08' + CHESSBOARD = b'\x14*\x14*\x14' + TRIANGLE_LEFT = b'\x02\x06\n\x12>' + TRIANGLE = b'\x00\x08\x14>\x00' + SNAKE = b'\x066\x14\x1c\x00' + UMBRELLA = b'\x1c>\x08\n\x0c' + SKULL = b'\x1c*>\x1c\x1c' + GIRAFFE = b'\x06\x04\x04\x1c\x14' + SWORD = b'\x08\x08\x08\x1c\x08' diff --git a/mixly/boards/default_src/micropython/origin/build/lib/max30102.py b/mixly/boards/default_src/micropython/origin/build/lib/max30102.py new file mode 100644 index 00000000..b2ce1eaa --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/max30102.py @@ -0,0 +1,291 @@ +""" +MAX30102 + +MicroPython library for the MAX30102(bmp_and_spo2) +======================================================= + +#Preliminary composition 20220723 +#base on https://github.com/doug-burrell/max30102.git 20220723 + +dahanzimin From the Mixly Team +""" + +import time +from micropython import const + +# Address of each register. +REG_INTR_STATUS_1 = const(0x00) +REG_INTR_STATUS_2 = const(0x01) +REG_INTR_ENABLE_1 = const(0x02) +REG_INTR_ENABLE_2 = const(0x03) +REG_FIFO_WR_PTR = const(0x04) +REG_OVF_COUNTER = const(0x05) +REG_FIFO_RD_PTR = const(0x06) +REG_FIFO_DATA = const(0x07) +REG_FIFO_CONFIG = const(0x08) +REG_MODE_CONFIG = const(0x09) +REG_SPO2_CONFIG = const(0x0A) +REG_LED1_PA = const(0x0C) +REG_LED2_PA = const(0x0D) +REG_PILOT_PA = const(0x10) +REG_MULTI_LED_CTRL1 = const(0x11) +REG_MULTI_LED_CTRL2 = const(0x12) +REG_TEMP_INTR = const(0x1F) +REG_TEMP_FRAC = const(0x20) +REG_TEMP_CONFIG = const(0x21) +REG_PART_ID = const(0xFF) + +class MAX30102: + def __init__(self, i2c, address=0x57): + """Initiate MAX30102 class ond each function responsible for correct device start-up""" + self._device = i2c + self._address = address + + if self._chip_id() != 0x15: + raise AttributeError("Cannot find a MAX30102") + + self.reset() + time.sleep(1) + self.setup() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(REG_PART_ID) + + def reset(self): + """Set default values of all registers""" + self._wreg(REG_MODE_CONFIG, 0x40) + + def shutdown(self): + """Shutdown the device""" + self._wreg(mode_config, 0x80) # 0b10000000 = 0x80 + + def setup(self,led_mode=0x03): + """Set all registers needed to correct work of sensor""" + self._wreg(REG_INTR_ENABLE_1, 0xC0) # 0xc0 : A_FULL_EN and PPG_RDY_EN = Interrupt will be triggered when + self._wreg(REG_INTR_ENABLE_2, 0x00) # fifo almost full & new fifo data ready + + self._wreg(REG_FIFO_WR_PTR, 0x00) # FIFO_WR_PTR[4:0] + self._wreg(REG_OVF_COUNTER, 0x00) # OVF_COUNTER[4:0] + self._wreg(REG_FIFO_RD_PTR, 0x00) # FIFO_RD_PTR[4:0] + + self._wreg(REG_FIFO_CONFIG, 0x4F) # sample avg = 4, fifo rollover = false, fifo almost full = 17 + self._wreg(REG_MODE_CONFIG, led_mode) # 0x02 for read-only, 0x03 for SpO2 mode, 0x07 multimode LED + self._wreg(REG_SPO2_CONFIG, 0x27) # SPO2_ADC range = 4096nA, SPO2 sample rate = 100Hz, LED pulse-width = 411uS + + self._wreg(REG_LED1_PA, 0x40) # choose value for ~7mA for LED1 + self._wreg(REG_LED2_PA, 0x40) # choose value for ~7mA for LED2 + self._wreg(REG_PILOT_PA, 0x7F) # choose value fro ~25mA for Pilot LED + + def get_data_present(self): + read_ptr = self._rreg(REG_FIFO_RD_PTR) + write_ptr = self._rreg(REG_FIFO_WR_PTR) + if read_ptr == write_ptr: + return 0 + else: + num_samples = write_ptr - read_ptr # account for pointer wrap around + if num_samples < 0: + num_samples += 32 + return num_samples + + def read_fifo(self): + """This function will read the data register""" + reg_INTR1 = self._rreg(REG_INTR_STATUS_1) + reg_INTR2 = self._rreg(REG_INTR_STATUS_2) + d = self._rreg(REG_FIFO_DATA, 6) + + red_led = (d[0] << 16 | d[1] << 8 | d[2]) & 0x03FFFF + ir_led = (d[3] << 16 | d[4] << 8 | d[5]) & 0x03FFFF + return ir_led,red_led + + def read_sequential(self, amount=100): + """This function will read the red-led and ir-led `amount` times""" + red_buf = [] + ir_buf = [] + count = amount + while count > 0: + num_bytes = self.get_data_present() + while num_bytes > 0: + ir, red = self.read_fifo() + red_buf.append(red) + ir_buf.append(ir) + num_bytes -= 1 + count -= 1 + return ir_buf,red_buf + + def temperature(self): + """Read temperature as sum of integer and fraction value """ + self._wreg(REG_TEMP_CONFIG, 0x01) + status = self._rreg(REG_INTR_STATUS_2) + count = 1 + while status != 2 and count < 5: + status = self._rreg(REG_INTR_STATUS_2) + count += 1 + integer = self._rreg(REG_TEMP_INTR) + fraction = self._rreg(REG_TEMP_FRAC) + return round(integer + fraction * 0.0625,2) + + def heartrate(self,amount=5): + bpms = [] + sop2 = [] + for _ in range(amount): + ir_data, red_data=self.read_sequential() + if get_mean(ir_data) < 50000 and get_mean(red_data) < 50000 : + return 0,0 + raw_bpm, valid_bpm, raw_spo2, valid_spo2 = calc_hr_and_spo2(ir_data, red_data) + if valid_bpm: + bpms.append(raw_bpm) + if valid_spo2: + sop2.append(raw_spo2) + bpms_len=len(bpms) + sop2_len=len(sop2) + if bpms_len<=2 or sop2_len<=2: + return 0,0 + else: + return sum(sorted(bpms)[1:bpms_len-1])//(bpms_len-2),round(sum(sorted(sop2)[1:sop2_len-1])/(sop2_len-2),2) + +"""-----------以下心率算法-----------""" + +SAMPLE_FREQ = 25 # 25 samples per second +MA_SIZE = 4 +BUFFER_SIZE = 100 # sampling frequency * 4 + +def get_mean(ls): + return sum(ls)/len(ls) + +def calc_hr_and_spo2(ir_data, red_data): + ir_mean = int(get_mean(ir_data)) + x = [] + for k in ir_data: + x.append((k-ir_mean)*-1) + for i in range(len(x) - MA_SIZE): + x[i] = sum(x[i:i+MA_SIZE]) / MA_SIZE + + n_th = int(get_mean(x)) + n_th = 30 if n_th < 30 else n_th # min allowed + n_th = 60 if n_th > 60 else n_th # max allowed + + ir_valley_locs, n_peaks = find_peaks(x, BUFFER_SIZE, n_th, 4, 15) + peak_interval_sum = 0 + if n_peaks >= 2: + for i in range(1, n_peaks): + peak_interval_sum += (ir_valley_locs[i] - ir_valley_locs[i-1]) + peak_interval_sum = int(peak_interval_sum / (n_peaks - 1)) + hr = int(SAMPLE_FREQ * 60 / peak_interval_sum) + hr_valid = True + else: + hr = -999 + hr_valid = False + + exact_ir_valley_locs_count = n_peaks + for i in range(exact_ir_valley_locs_count): + if ir_valley_locs[i] > BUFFER_SIZE: + spo2 = -999 + spo2_valid = False + return hr, hr_valid, spo2, spo2_valid + i_ratio_count = 0 + ratio = [] + # find max between two valley locations + red_dc_max_index = -1 + ir_dc_max_index = -1 + for k in range(exact_ir_valley_locs_count-1): + red_dc_max = -16777216 + ir_dc_max = -16777216 + if ir_valley_locs[k+1] - ir_valley_locs[k] > 3: + for i in range(ir_valley_locs[k], ir_valley_locs[k+1]): + if ir_data[i] > ir_dc_max: + ir_dc_max = ir_data[i] + ir_dc_max_index = i + if red_data[i] > red_dc_max: + red_dc_max = red_data[i] + red_dc_max_index = i + + red_ac = int((red_data[ir_valley_locs[k+1]] - red_data[ir_valley_locs[k]]) * (red_dc_max_index - ir_valley_locs[k])) + red_ac = red_data[ir_valley_locs[k]] + int(red_ac / (ir_valley_locs[k+1] - ir_valley_locs[k])) + red_ac = red_data[red_dc_max_index] - red_ac # subtract linear DC components from raw + + ir_ac = int((ir_data[ir_valley_locs[k+1]] - ir_data[ir_valley_locs[k]]) * (ir_dc_max_index - ir_valley_locs[k])) + ir_ac = ir_data[ir_valley_locs[k]] + int(ir_ac / (ir_valley_locs[k+1] - ir_valley_locs[k])) + ir_ac = ir_data[ir_dc_max_index] - ir_ac # subtract linear DC components from raw + + nume = red_ac * ir_dc_max + denom = ir_ac * red_dc_max + if (denom > 0 and i_ratio_count < 5) and nume != 0: + ratio.append(int(((nume * 100) & 0xffffffff) / denom)) + i_ratio_count += 1 + # choose median value since PPG signal may vary from beat to beat + ratio = sorted(ratio) # sort to ascending order + mid_index = int(i_ratio_count / 2) + + ratio_ave = 0 + if mid_index > 1: + ratio_ave = int((ratio[mid_index-1] + ratio[mid_index])/2) + else: + if len(ratio) != 0: + ratio_ave = ratio[mid_index] + + if ratio_ave > 2 and ratio_ave < 184: + # -45.060 * ratioAverage * ratioAverage / 10000 + 30.354 * ratioAverage / 100 + 94.845 + spo2 = -45.060 * (ratio_ave**2) / 10000.0 + 30.054 * ratio_ave / 100.0 + 94.845 + spo2_valid = True + else: + spo2 = -999 + spo2_valid = False + + return hr, hr_valid, spo2, spo2_valid + +def find_peaks(x, size, min_height, min_dist, max_num): + """ Find at most MAX_NUM peaks above MIN_HEIGHT separated by at least MIN_DISTANCE""" + ir_valley_locs, n_peaks = find_peaks_above_min_height(x, size, min_height, max_num) + ir_valley_locs, n_peaks = remove_close_peaks(n_peaks, ir_valley_locs, x, min_dist) + n_peaks = min([n_peaks, max_num]) + return ir_valley_locs, n_peaks + +def find_peaks_above_min_height(x, size, min_height, max_num): + """Find all peaks above MIN_HEIGHT """ + i = 0 + n_peaks = 0 + ir_valley_locs = [] # [0 for i in range(max_num)] + while i < size - 1: + if x[i] > min_height and x[i] > x[i-1]: # find the left edge of potential peaks + n_width = 1 + while i + n_width < size - 1 and x[i] == x[i+n_width]: # find flat peaks + n_width += 1 + if x[i] > x[i+n_width] and n_peaks < max_num: # find the right edge of peaks + ir_valley_locs.append(i) + n_peaks += 1 # original uses post increment + i += n_width + 1 + else: + i += n_width + else: + i += 1 + + return ir_valley_locs, n_peaks + +def remove_close_peaks(n_peaks, ir_valley_locs, x, min_dist): + """ Remove peaks separated by less than MIN_DISTANCE""" + sorted_indices = sorted(ir_valley_locs, key=lambda i: x[i]) + sorted_indices.reverse() + + i = -1 + while i < n_peaks: + old_n_peaks = n_peaks + n_peaks = i + 1 + j = i + 1 + while j < old_n_peaks: + n_dist = (sorted_indices[j] - sorted_indices[i]) if i != -1 else (sorted_indices[j] + 1) # lag-zero peak of autocorr is at index -1 + if n_dist > min_dist or n_dist < -1 * min_dist: + sorted_indices[n_peaks] = sorted_indices[j] + n_peaks += 1 # original uses post increment + j += 1 + i += 1 + + sorted_indices[:n_peaks] = sorted(sorted_indices[:n_peaks]) + return sorted_indices, n_peaks diff --git a/mixly/boards/default_src/micropython/origin/build/lib/mixgo_ai.py b/mixly/boards/default_src/micropython/origin/build/lib/mixgo_ai.py new file mode 100644 index 00000000..9925315f --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/mixgo_ai.py @@ -0,0 +1,206 @@ +""" +AI COM + +MicroPython library for the AI COM ( for MixGo AI) +======================================================= + +#Preliminary composition 20220905 + +dahanzimin From the Mixly Team +""" + +import time,gc + + +class INFO: + def __init__(self, info1,info2,rect): + self.info1=info1 + self.info2=info2 + self.rect=rect + self.x=None + self.y=None + self.w=None + self.h=None + self.xc=None + self.yc=None + if type(rect) in [tuple,list]: + self.x=rect[0] + self.y=rect[1] + self.w=rect[2] + self.h=rect[3] + self.xc=rect[0]+rect[2]//2 + self.yc=rect[1]+rect[3]//2 + self.type="info" + +class AI: + def __init__(self, uart, quick=False): + self._uart=uart + self._uart.init(baudrate=115200, timeout=500) + self._info=[] + self._sdata=[] + self._removal=quick + if not self._chip_id(): + raise AttributeError("Cannot find a MixGo AI") + + def send(self,data): + eec=0 + buffer=str(data).encode() + for i in range(len(buffer)): + eec^=int(buffer[i]) + eec=0 if eec==10 else eec + self._uart.write(buffer+chr(eec)+b'\n') + + def recv(self,timeout=500,warn=True): + t_star=time.ticks_ms() + while not self._uart.any(): + if time.ticks_diff(time.ticks_ms(), t_star) >timeout: + if warn: + print("Warning: MixGo AI timeout not responding") + return False + buffer = self._uart.readline() + if buffer: + eec=0 + if len(buffer)>=3: + for i in range(len(buffer)-2): + eec^=int(buffer[i]) + if eec==buffer[-2] or buffer[-2]==0: + try: + return eval(buffer[:-2].decode()) + except: + return None + def _chip_id(self): + for _ in range(10): + self.send(["ok",[[],'']]) + if self.recv(1000,False): + return True + + def request(self,func='', para=[], name=None, timeout=1000): + if self._sdata != para: + self._sdata=para if self._removal else None + self.send([func,[para,name]]) + else: + self.send([func,[[],name]]) + + #print(func) + if func in ['ailr','ailt','play','record','asr']: #不需要警告提醒 + data=self.recv(timeout,False) + else: + data=self.recv(timeout,True) + + self._info=[] + if data: + #报错处理 + if "err" in data[0] and type(data[1])==list: + if type(data[1][0]) == IndexError or "Missing parameter" == data[1][0]: + self.send(["ok",[[],name]]) #恢复出厂 + self.send([func,[para,name]]) #在发送参数 + else: + raise RuntimeError("Error from MixGo AI",data[1][0]) + else: + _len=max(len(data[0]),len(data[1])) + for i in range(_len): + if type(data[0][i]) == list: + info1=data[0][i][0] + info2=data[0][i][1] + else: + info1=data[0][i] + info2=None + + if data[1]: + rect=data[1][i] + else: + rect=None + self._info.append(INFO(info1,info2,rect)) + return self._info + + def info_len(self): + return len(self._info) + + def info_number(self,number): + if self.info_len() > number: + return self._info[number] + + def configure(self, tx_pin, rx_pin, restart=False): + info=self.request('start',para=[["uart",tx_pin,rx_pin],restart]) + return info[0].info1 if info else False + + def find_qrcode(self): + info=self.request('qr') + return (info[0].info1,info[0].rect) if info else (None,None) + + def find_barcode(self): + info=self.request('bar') + return (info[0].info1,info[0].rect) if info else (None,None) + + def find_apriltag(self): + info=self.request('tag') + return (info[0].info1,info[0].rect) if info else (None,None) + + def find_qrcodes(self): + return self.request('qr') + + def find_barcodes(self): + return self.request('bar') + + def find_apriltags(self): + return self.request('tag') + + def find_lines(self, threshold=2500, theta_margin=25, rho_margin=25): + return self.request('line', para=[threshold, theta_margin, rho_margin]) + + def find_circles(self, threshold=2500, r_min=2, r_max=100): + return self.request('circle', para=[threshold, r_min, r_max]) + + def find_rects(self, threshold=2500): + return self.request('rect', para=[threshold]) + + def find_colors(self, scale=2): + info=self.request('color', para=[scale]) + if info: + return info[0].info1,info[0].info2 + else: + return None,None + + def color_track(self, lab=[0, 100, 0, 100, 0, 0], pixels_threshold=10, margin=1): + return self.request('ctrace', para=[lab, pixels_threshold, margin]) + + def ailocal_train(self, lsit_names, path="mixgo", number=5, disname='自模型训练'): + info= self.request('ailt', para=[lsit_names, path, number], name=disname) + return info[0].info1 if info else False + + def ailocal_class(self, lsit_names, path="mixgo", disname='自模型识别'): + return self.request('ailr', para=[lsit_names, path], name=disname) + + def yolo_recognize(self, anchor, path, disname='物品识别'): + return self.request('aild', para=[anchor, path], name=disname) + + def led_rgb(self, rgb1=(0,0,0), rgb2=(0,0,0)): + info= self.request('rgb', para=[rgb1, rgb2]) + return info[0].info1 if info else False + + def audio_play(self, bck_pin=12, ws_pin=13, dat_pin=14, path="mixgo.wav", volume=80): + info= self.request('play', para=[[bck_pin, ws_pin, dat_pin], path, volume]) + return info[0].info1 if info else False + + def audio_record(self, sample_rate=16000, path="mixgo.wav", times=5): + info= self.request('record', para=[sample_rate, path, times]) + return info[0].info1 if info else False + + def asr_recognize(self, corpus,threshold=0.1): + clist=[] + for cor in corpus: + clist.append([cor,threshold]) + info=self.request('asr', para=[dict(clist)]) + if info: + return info[0].info1,info[0].info2 + else: + return None,None + + def find_licenseplate(self): + return self.request('alpr') + + def find_20object(self): + return self.request('voc20') + + def face_detect(self): + return self.request('face_d') diff --git a/mixly/boards/default_src/micropython/origin/build/lib/mixiot.py b/mixly/boards/default_src/micropython/origin/build/lib/mixiot.py new file mode 100644 index 00000000..6cbf09c6 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/mixiot.py @@ -0,0 +1,353 @@ +import time +import usocket as socket +import ustruct as struct +from machine import unique_id +from ubinascii import hexlify +from matcher import MQTTMatcher + +ADDITIONAL_TOPIC = 'b640a0ce465fa2a4150c36b305c1c11b' +WILL_TOPIC = '9d634e1a156dc0c1611eb4c3cff57276' + +def wlan_connect(ssid='MYSSID', password='MYPASS', timeout=10): + import network + wlan = network.WLAN(network.STA_IF) + if not wlan.active(): + wlan.active(True) + time.sleep(0.5) + if not wlan.isconnected(): + print('connecting to:', ssid, end ="") + try: + wlan.connect(ssid, password) + except: + pass + _num = 0 + while not wlan.isconnected(): + _num += 1 + time.sleep(1) + print('.',end ="") + if _num > timeout: + wlan.active(False) + print('') + import os + if 'c5' in os.uname().machine.lower(): + raise RuntimeError("WiFi connection timeout. Please check the SSID and password") + else: + raise RuntimeError("WiFi connection timeout, Please check the SSID and password (only 2.4GHz networks are supported)") + print('\nnetwork config:', wlan.ifconfig()) + return wlan + +def image_base64(path="mixly.jpg"): + from base64 import b64encode + if isinstance(path, str): + with open(path, 'rb') as f: + _data = f.read() + return 'data:image/{};base64,'.format(path.split('.')[-1]).encode() + b64encode(_data) + else: + return b'data:image/jpg;base64,' + b64encode(path) + +def ntp(url='mixio.mixly.cn'): + import urequests + try: + results=eval(urequests.get('http://{}/time.php'.format(url)).text) + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected",e) + return results + +def init_MQTT_client(address, username, password,MQTT_USR_PRJ): + client = MQTTClient(hexlify(unique_id()), address, 1883, username, password) + client.set_last_will(topic=MQTT_USR_PRJ+WILL_TOPIC, msg=client.client_id, qos=2) + if client.connect()==0: + client.publish(MQTT_USR_PRJ+ADDITIONAL_TOPIC, client.client_id, qos=0) + time.sleep_ms(200) + return client + +# Add by Mixly Team +def str_len(object): + if isinstance(object, str): + return len(object.encode('utf-8')) + else: + return len(object) +##################################################### + +class MQTTException(Exception): + pass + +class MQTTClient: + def __init__(self, client_id, server, port=0, username=None, password=None, keepalive=60, ssl=False, ssl_params={}): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = None + self.server = server + self.addr = socket.getaddrinfo(server, port)[0][-1] + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self._on_message = None + self.username = username + self.password = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + self._on_message_filtered = MQTTMatcher() + self._star_time = time.ticks_ms() + + def _send_str(self, s): + self.sock.write(struct.pack("!H", str_len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, mqtt_topic, callback_method, MQTT_USR_PRJ): + """Registers a callback_method for a specific MQTT topic""" + if mqtt_topic is None or callback_method is None: + raise ValueError("MQTT topic and callback method must both be defined.") + self._on_message_filtered[MQTT_USR_PRJ+mqtt_topic] = callback_method + + def remove_callback(self, mqtt_topic): + """Removes a registered callback method""" + if mqtt_topic is None: + raise ValueError("MQTT Topic must be defined.") + try: + del self._on_message_filtered[mqtt_topic] + except KeyError: + raise KeyError( + "MQTT topic callback not added with add_topic_callback." + ) from None + + @property + def on_message(self): + """Called when a new message has been received on a subscribed topic""" + return self._on_message + + @on_message.setter + def on_message(self, method): + self._on_message = method + + def _handle_on_message(self, client, topic, message): + matched = False + if topic is not None: + for callback in self._on_message_filtered.iter_match(topic): + callback(client, topic.split("/")[-1], message) # on_msg with callback + matched = True + + if not matched and self.on_message: # regular on_message + self.on_message(client, topic.split("/")[-1], message) + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + self.sock = socket.socket() + self.sock.connect(self.addr) + print(self.addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) + msg_header=bytearray([0x10]) + msg = bytearray(b"\x04MQTT\x04\x02\0\0") + msg_length = 12 + str_len(self.client_id) + msg[6] = clean_session << 1 + + if self.username is not None: + msg_length += 2 + str_len(self.username) + 2 + str_len(self.password) + msg[6] |= 0xC0 + if self.keepalive: + assert self.keepalive < 65536 + msg[7] |= self.keepalive >> 8 + msg[8] |= self.keepalive & 0x00FF + if self.lw_topic: + msg_length += 2 + str_len(self.lw_topic) + 2 + str_len(self.lw_msg) + msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 + msg[6] |= self.lw_retain << 5 + + if msg_length > 0x7F: + while msg_length>0: + encoded_byte = msg_length % 0x80 + msg_length = msg_length // 0x80 + if msg_length > 0: + encoded_byte |= 0x80 + msg_header.append(encoded_byte) + msg_header.append(0x00) + else: + msg_header.append(msg_length) + msg_header.append(0x00) + + self.sock.write(msg_header) + self.sock.write(msg) + #print(hexlify(msg_header, ":"), hexlify(msg, ":")) + self._send_str(self.client_id) + if self.lw_topic: + self._send_str(self.lw_topic) + self._send_str(self.lw_msg) + if self.username is not None: + self._send_str(self.username) + self._send_str(self.password) + resp = self.sock.read(4) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + if resp[3] == 1: + raise MQTTException("Unsupported Protocol") + elif resp[3] == 2: + raise MQTTException("Illegal ClientID") + elif resp[3] == 3: + raise MQTTException("Server Unavailable") + elif resp[3] == 4: + raise MQTTException("Invalid username and password format") + elif resp[3] == 5: + raise MQTTException("Unauthorized") + else: + raise MQTTException(resp[3]) + return resp[2] & 1 + + + def disconnect(self,MQTT_USR_PRJ): + #MQTT_USR_PRJ = "{}/{}/".format(self.username,self.project) + self.publish(MQTT_USR_PRJ+WILL_TOPIC, self.client_id, qos=1) + self.sock.write(b"\xe0\0") + self.sock.close() + + def ping(self): + self.sock.write(b"\xc0\0") + + def pingSync(self): + self.ping() + for i in range(0,10): + msg = self.check_msg() + if msg == "PINGRESP": + return True + time.sleep_ms(100) + return False + + def publish(self, topic, msg, retain=False, qos=0): + # msg = pubData(msg) + if "+" in topic or "#" in topic: + raise MQTTException("Publish topic can not contain wildcards.") + # check msg/qos kwargs + if msg is None: + raise MQTTException("Message can not be None.") + if isinstance(msg, (int, float)): + msg = str(msg).encode("ascii") + elif isinstance(msg, str): + msg = str(msg).encode("utf-8") + elif isinstance(msg, bytes): + pass + else: + raise MQTTException("Invalid message data type.") + pkt = bytearray(b"\x30\0\0\0") + pkt[0] |= qos << 1 | retain + sz = 2 + str_len(topic) + str_len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + #print(hex(str_len(pkt)), hexlify(pkt, ":")) + self.sock.settimeout(0.05) + #self.sock.setblocking(True) + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.pid += 1 + pid = self.pid + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + if qos == 1: + while 1: + op = self.wait_msg() + if op == 0x40: + sz = self.sock.read(1) + assert sz == b"\x02" + rcv_pid = self.sock.read(2) + rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid == rcv_pid: + return + elif qos == 2: + assert 0 + + def subscribe(self, topic, qos=0): + #assert self.cb is not None, "Subscribe callback is not set" + pkt = bytearray(b"\x82\0\0\0") + self.pid += 1 + if isinstance(topic, str): + topic=topic.encode() + struct.pack_into("!BH", pkt, 1, 2 + 2 + str_len(topic) + 1, self.pid) + #print(hex(str_len(pkt)), hexlify(pkt, ":")) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + while 1: + op = self.wait_msg() + if op == 0x90: + resp = self.sock.read(4) + #print(resp) + assert resp[1] == pkt[2] and resp[2] == pkt[3] + if resp[3] == 0x80: + raise MQTTException(resp[3]) + return + + # Wait for a single incoming MQTT message and process it. + def wait_msg(self): + res = self.sock.read(1) + time.sleep_ms(50) + self.sock.settimeout(0.05) + #self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return "PINGRESP" + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len) + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz) + self._handle_on_message(self, str(topic, "utf-8"), str(msg, "utf-8")) + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + # Checks whether a pending message from server is available. + def check_msg(self): + self.sock.settimeout(0.05) + if time.ticks_diff(time.ticks_ms(), self._star_time) >60000: + self._star_time = time.ticks_ms() + self.ping() + return self.wait_msg() + + def get_server_info(self): + return (self.server, self.username, self.password) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/mixpy.py b/mixly/boards/default_src/micropython/origin/build/lib/mixpy.py new file mode 100644 index 00000000..cb27e595 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/mixpy.py @@ -0,0 +1,94 @@ +#coding=utf-8 +import math + +def math_map(v, al, ah, bl, bh): + if al==ah: + return bl + if al < ah: + v = max(min(ah,v),al) + if al > ah: + v = max(min(al,v),ah) + return bl + (bh - bl) * (v - al) / (ah - al) + +def math_mean(myList): + localList = [e for e in myList if type(e) == int or type(e) == float] + if not localList: return + return float(sum(localList)) / len(localList) + +def math_median(myList): + localList = sorted([e for e in myList if type(e) == int or type(e) == float]) + if not localList: return + if len(localList) % 2 == 0: + return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0 + else: + return localList[(len(localList) - 1) // 2] + +def math_modes(some_list): + modes = [] + # Using a lists of [item, count] to keep count rather than dict + # to avoid "unhashable" errors when the counted item is itself a list or dict. + counts = [] + maxCount = 1 + for item in some_list: + found = False + for count in counts: + if count[0] == item: + count[1] += 1 + maxCount = max(maxCount, count[1]) + found = True + if not found: + counts.append([item, 1]) + for counted_item, item_count in counts: + if item_count == maxCount: + modes.append(counted_item) + return modes + +def math_standard_deviation(numbers): + n = len(numbers) + if n == 0: return + mean = float(sum(numbers)) / n + variance = sum((x - mean) ** 2 for x in numbers) / n + return math.sqrt(variance) + +def lists_sort(my_list, type, reverse): + def try_float(s): + try: + return float(s) + except: + return 0 + key_funcs = { + "NUMERIC": try_float, + "TEXT": str, + "IGNORE_CASE": lambda s: str(s).lower() + } + key_func = key_funcs[type] + list_cpy = list(my_list) + return sorted(list_cpy, key=key_func, reverse=reverse) + +def format_content(mydict, cid): + if 'lat' in mydict and 'long' in mydict: + res = '{'+'"lat": "{}", "long": "{}", "clientid": "{}"'.format(mydict.pop('lat'),mydict.pop('long'),cid) + if len(mydict)>0: + res += ', "message": [' + for d in mydict: + res += '{{"label": "{}", "value": "{}"}},'.format(d,mydict[d]) + res = res[:-1] + "]" + res += '}' + return res + else: + print('Invalid Input') + +def format_str(d): + return str(d).replace("'",'"') + + +def analyse_sharekey(url): + import urequests + import json + response = urequests.get(url) + + if response.text == '-1': + raise AttributeError('Invalid share key') + else: + result = json.loads(response.text) + return (result['0'], result['1'], result['2']) \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/mk_pb4023.py b/mixly/boards/default_src/micropython/origin/build/lib/mk_pb4023.py new file mode 100644 index 00000000..8ff85db2 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/mk_pb4023.py @@ -0,0 +1,74 @@ +""" +MK-PB4023PS&ASL&VC-A01E + +MicroPython library for the MK-PB4023PS&ASL&VC-A01E (PS,ASL,CS) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_MK_SYSM = const(0x80) +_MK_ID = const(0x98) +_MK_DATA = const(0xA0) + +class MK_PB4023: + def __init__(self, i2c_bus, addr=0x39): + self._device = i2c_bus + self._address = addr + if self._rreg(_MK_ID) != 0xA0: + raise AttributeError("Cannot find a MK-PB4023") + self._configure() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes) + + def _configure(self): + '''Configuration Register''' + self._wreg(0X82, 0x80) + self._wreg(0x83, 0x01) + self._wreg(0x84, 0x07) + self._wreg(0x85, 0x0B) + self._wreg(0x86, 0x03) + self._wreg(0x87, 0x1A) + self._wreg(0x89, 0x38) + self._wreg(_MK_SYSM,0x0F) #Enable Register + + def getdata(self): + '''Processing data acquisition''' + _buf = self._rreg(_MK_DATA, 12) + _r = _buf[0] | _buf[1] << 8 + _g = _buf[2] | _buf[3] << 8 + _b = _buf[4] | _buf[5] << 8 + _c = _buf[6] | _buf[7] << 8 + _ir = _buf[8] | _buf[9] << 8 + _ps = _buf[10] | _buf[11] << 8 + return _c, _ir, (_r, _g, _b), _ps + + def color(self): + w, _, (r, g, b), _ = self.getdata() + if w == 0: + return (0, 0, 0) + else: + red = int(pow((int((r / w) * 256) / 255), 2.5) * 255) + green = int(pow((int((g / w) * 256) / 255), 2.5) * 255) + blue = int(pow((int((b / w) * 256) / 255), 2.5) * 255) + return (min(red, 255), min(green, 255), min(blue, 255)) + + def color_raw(self): + return self.getdata()[2] + + def ir(self): + return self.getdata()[1] + + def als(self): + w, ir, (r, g, b), _ = self.getdata() + return round((w + ir + r + g + b) / 17.8, 2) + + def ps(self): + return self.getdata()[3] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/mmc5603.py b/mixly/boards/default_src/micropython/origin/build/lib/mmc5603.py new file mode 100644 index 00000000..6446e6c1 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/mmc5603.py @@ -0,0 +1,149 @@ +""" +MMC5603 + +Micropython library for the MMC5603NJ(Magnetic) +======================================================= + +#Preliminary composition 20221017 + +dahanzimin From the Mixly Team +""" +import time,math +from micropython import const + +MMC5603_ADDRESS = const(0x30) + +MMC5603_REG_DATA = const(0x00) +MMC5603_REG_TMP = const(0x09) +MMC5603_REG_ODR = const(0x1A) +MMC5603_REG_CTRL0 = const(0x1B) +MMC5603_REG_CTRL1 = const(0x1C) +MMC5603_REG_CTRL2 = const(0x1D) + +MMC5603_REG_X_THD = const(0x1E) +MMC5603_REG_Y_THD = const(0x1F) +MMC5603_REG_Z_THD = const(0x20) +MMC5603_REG_ST_X_VAL = const(0x27) +MMC5603_REG_DEVICE_ID = const(0x39) + +class MMC5603: + def __init__(self, i2c_bus): + self._device = i2c_bus + self._address = MMC5603_ADDRESS + self.raw_x = 0.0 + self.raw_y = 0.0 + self.raw_z = 0.0 + + if self._chip_id() != 0x10: #Check product ID + raise AttributeError("Cannot find a MMC5603") + try: #Read calibration file + import magnetic_cal + self._offset_x = magnetic_cal._offset_x + self._offset_y = magnetic_cal._offset_y + self._offset_z = magnetic_cal._offset_z + except: + self._offset_x = 524288 + self._offset_y = 524288 + self._offset_z = 524288 + #print("offset:",self._offset_x ,self._offset_y,self._offset_z) + + self._auto_selftest() #Auto self-test registers configuration + self._set() + self._continuous_mode(0x00, 50) #Work mode setting + time.sleep(0.05) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(MMC5603_REG_DEVICE_ID) + + def _auto_selftest(self): + '''Auto self-test registers configuration''' + st_thd_reg=[0,0,0] + st_thr_data=[0,0,0] + #/* Read trim data from reg 0x27-0x29 */ + _buffer=self._rreg(MMC5603_REG_ST_X_VAL,3) + for i in range(0, 3, 1): + st_thr_data[i]=(_buffer[i]-128)*32 + if st_thr_data[i] < 0: + st_thr_data[i]=-st_thr_data[i] + st_thd=(st_thr_data[i]-st_thr_data[i]//5)//8 + if st_thd > 255: + st_thd_reg[i]=0xFF + else: + st_thd_reg[i]=st_thd + #/* Write threshold into the reg 0x1E-0x20 */ + self._wreg(MMC5603_REG_X_THD, st_thd_reg[0]) + self._wreg(MMC5603_REG_Y_THD, st_thd_reg[1]) + self._wreg(MMC5603_REG_Z_THD, st_thd_reg[2]) + + def _set(self): + '''Do SET operation''' + self._wreg(MMC5603_REG_CTRL0, 0X08) + time.sleep(0.005) + + def _continuous_mode(self,bandwith,sampling_rate): + '''Work mode setting''' + self._wreg(MMC5603_REG_CTRL1, bandwith) + self._wreg(MMC5603_REG_ODR, sampling_rate) + self._wreg(MMC5603_REG_CTRL0, 0X80|0X20) + self._wreg(MMC5603_REG_CTRL2, 0x10) + + def getdata(self): + _buf=self._rreg( MMC5603_REG_DATA,9) + #/* Transform to unit Gauss */ + self.raw_x=(_buf[0] << 12) | (_buf[1] << 4) | (_buf[6] >> 4) + self.raw_y=(_buf[2] << 12) | (_buf[3] << 4) | (_buf[7] >> 4) + self.raw_z=(_buf[4] << 12) | (_buf[5] << 4) | (_buf[8] >> 4) + return (-0.0625*(self.raw_x-self._offset_x), -0.0625*(self.raw_y-self._offset_y), -0.0625*(self.raw_z-self._offset_z)) + + def calibrate(self): + print("The magnetic field will be calibrated") + print("Please pick up the board and rotate the '8' shape in the air") + time.sleep(2) + self.getdata() + min_x = max_x = self.raw_x + min_y = max_y = self.raw_y + min_z = max_z = self.raw_z + ticks_start = time.ticks_ms() + while (time.ticks_diff(time.ticks_ms(), ticks_start) < 20000) : + self.getdata() + min_x = min(self.raw_x, min_x) + max_x = max(self.raw_x, max_x) + min_y = min(self.raw_y, min_y) + max_y = max(self.raw_y, max_y) + min_z = min(self.raw_z, min_z) + max_z = max(self.raw_z, max_z) + time.sleep_ms(20) + if time.ticks_diff(time.ticks_ms(), ticks_start) % 20 ==0: + print("=",end ="") + print(" 100%") + self._offset_x = (max_x + min_x) / 2 + self._offset_y = (max_y + min_y) / 2 + self._offset_z = (max_z + min_z) / 2 + print("Save x_offset:{}, y_offset:{}, z_offset:{}".format(self._offset_x,self._offset_y,self._offset_z)) + s_f = open("magnetic_cal.py", "w+") + s_f.write("_offset_x="+str(self._offset_x)+"\n") + s_f.write("_offset_y="+str(self._offset_y)+"\n") + s_f.write("_offset_z="+str(self._offset_z)+"\n") + s_f.close() + time.sleep(2) + + def getstrength(self): + _x,_y,_z=self.getdata() + return (math.sqrt(math.pow(_x, 2) + pow(_y, 2) + pow(_z, 2))) + + def getangle(self,upright=False): + _x,_y,_z=self.getdata() + if upright: #vertical + angle=math.atan2(_z, -_x)*(180 / math.pi) + 180 + 3 + return angle if angle<360 else angle-360 + else: #horizontal + angle=math.atan2(_y, -_x)*(180 / math.pi) + 180 + 3 + return angle if angle<360 else angle-360 diff --git a/mixly/boards/default_src/micropython/origin/build/lib/mpu9250.py b/mixly/boards/default_src/micropython/origin/build/lib/mpu9250.py new file mode 100644 index 00000000..da9ec659 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/mpu9250.py @@ -0,0 +1,585 @@ +""" +MicroPython I2C driver for MPU9250 9-axis motion tracking device +""" +from micropython import const +import ustruct +import time +import math +from machine import Pin,SoftI2C + +_GYRO_CONFIG = const(0x1b) +_ACCEL_CONFIG = const(0x1c) +_ACCEL_CONFIG2 = const(0x1d) +_INT_PIN_CFG = const(0x37) +_ACCEL_XOUT_H = const(0x3b) +_ACCEL_XOUT_L = const(0x3c) +_ACCEL_YOUT_H = const(0x3d) +_ACCEL_YOUT_L = const(0x3e) +_ACCEL_ZOUT_H = const(0x3f) +_ACCEL_ZOUT_L= const(0x40) +_TEMP_OUT_H = const(0x41) +_TEMP_OUT_L = const(0x42) +_GYRO_XOUT_H = const(0x43) +_GYRO_XOUT_L = const(0x44) +_GYRO_YOUT_H = const(0x45) +_GYRO_YOUT_L = const(0x46) +_GYRO_ZOUT_H = const(0x47) +_GYRO_ZOUT_L = const(0x48) +_WHO_AM_I = const(0x75) + +#_ACCEL_FS_MASK = const(0b00011000) +ACCEL_FS_SEL_2G = const(0b00000000) +ACCEL_FS_SEL_4G = const(0b00001000) +ACCEL_FS_SEL_8G = const(0b00010000) +ACCEL_FS_SEL_16G = const(0b00011000) + +_ACCEL_SO_2G = 16384 # 1 / 16384 ie. 0.061 mg / digit +_ACCEL_SO_4G = 8192 # 1 / 8192 ie. 0.122 mg / digit +_ACCEL_SO_8G = 4096 # 1 / 4096 ie. 0.244 mg / digit +_ACCEL_SO_16G = 2048 # 1 / 2048 ie. 0.488 mg / digit + +#_GYRO_FS_MASK = const(0b00011000) +GYRO_FS_SEL_250DPS = const(0b00000000) +GYRO_FS_SEL_500DPS = const(0b00001000) +GYRO_FS_SEL_1000DPS = const(0b00010000) +GYRO_FS_SEL_2000DPS = const(0b00011000) + +_GYRO_SO_250DPS = 131 +_GYRO_SO_500DPS = 62.5 +_GYRO_SO_1000DPS = 32.8 +_GYRO_SO_2000DPS = 16.4 + +# Used for enablind and disabling the i2c bypass access +_I2C_BYPASS_MASK = const(0b00000010) +_I2C_BYPASS_EN = const(0b00000010) +_I2C_BYPASS_DIS = const(0b00000000) + +SF_G = 1 +SF_M_S2 = 9.80665 # 1 g = 9.80665 m/s2 ie. standard gravity +SF_DEG_S = 1 +SF_RAD_S = 57.295779578552 # 1 rad/s is 57.295779578552 deg/s + + +_WIA = const(0x00) +_HXL = const(0x03) +_HXH = const(0x04) +_HYL = const(0x05) +_HYH = const(0x06) +_HZL = const(0x07) +_HZH = const(0x08) +_ST2 = const(0x09) +_CNTL1 = const(0x0a) +_ASAX = const(0x10) +_ASAY = const(0x11) +_ASAZ = const(0x12) + +_MODE_POWER_DOWN = 0b00000000 +MODE_SINGLE_MEASURE = 0b00000001 +MODE_CONTINOUS_MEASURE_1 = 0b00000010 # 8Hz +MODE_CONTINOUS_MEASURE_2 = 0b00000110 # 100Hz +MODE_EXTERNAL_TRIGGER_MEASURE = 0b00000100 +_MODE_SELF_TEST = 0b00001000 +_MODE_FUSE_ROM_ACCESS = 0b00001111 + +OUTPUT_14_BIT = 0b00000000 +OUTPUT_16_BIT = 0b00010000 + +_SO_14BIT = 0.6 # per digit when 14bit mode +_SO_16BIT = 0.15 # per digit when 16bit mode + +class MPU6500: + """Class which provides interface to MPU6500 6-axis motion tracking device.""" + def __init__( + self, i2c, address=0x68, + accel_fs=ACCEL_FS_SEL_2G, gyro_fs=GYRO_FS_SEL_250DPS, + accel_sf=SF_M_S2, gyro_sf=SF_RAD_S + ): + self.i2c = i2c + self.address = address + + if 0x71 != self.whoami: + raise RuntimeError("MPU9250 not found in I2C bus.") + + self._accel_so = self._accel_fs(accel_fs) + self._gyro_so = self._gyro_fs(gyro_fs) + self._accel_sf = accel_sf + self._gyro_sf = gyro_sf + + # Enable I2C bypass to access for MPU9250 magnetometer access. + char = self._register_char(_INT_PIN_CFG) + char &= ~_I2C_BYPASS_MASK # clear I2C bits + char |= _I2C_BYPASS_EN + self._register_char(_INT_PIN_CFG, char) + + @property + def temperature(self): + tempbuf=self._register_short(0x41) + return tempbuf/333.87 + 21 # I think + + # @property + def acceleration(self): + so = self._accel_so + sf = self._accel_sf + + xyz = self._register_three_shorts(_ACCEL_XOUT_H) + return tuple([value / so * sf for value in xyz]) + + @property + def gyro(self): + """ X, Y, Z radians per second as floats.""" + so = self._gyro_so + sf = self._gyro_sf + + xyz = self._register_three_shorts(_GYRO_XOUT_H) + return tuple([value / so * sf for value in xyz]) + + @property + def whoami(self): + """ Value of the whoami register. """ + return self._register_char(_WHO_AM_I) + + def _register_short(self, register, value=None, buf=bytearray(2)): + if value is None: + self.i2c.readfrom_mem_into(self.address, register, buf) + return ustruct.unpack(">h", buf)[0] + + ustruct.pack_into(">h", buf, 0, value) + return self.i2c.writeto_mem(self.address, register, buf) + + def _register_three_shorts(self, register, buf=bytearray(6)): + self.i2c.readfrom_mem_into(self.address, register, buf) + return ustruct.unpack(">hhh", buf) + + def _register_char(self, register, value=None, buf=bytearray(1)): + if value is None: + self.i2c.readfrom_mem_into(self.address, register, buf) + return buf[0] + + ustruct.pack_into("= 9: + return True + else: + return False + if choice == 'shake': + if abs(self.mpu6500.acceleration()[0]) >= 9 and abs(self.mpu6500.acceleration()[1]) >= 9 : + return True + else: + return False + if choice == 'up': + if self.mpu6500.acceleration()[1] >= 9: + return True + else: + return False + if choice == 'down': + if self.mpu6500.acceleration()[1] <= -9: + return True + else: + return False + if choice == 'right': + if self.mpu6500.acceleration()[0] <= -9: + return True + else: + return False + if choice == 'left': + if self.mpu6500.acceleration()[0] >= 9: + return True + else: + return False + + @property + def mpu9250_gyro(self): + return self.mpu6500.gyro + + def mpu9250_gyro_x(self): + return self.mpu6500.gyro[0] + + def mpu9250_gyro_y(self): + return self.mpu6500.gyro[1] + + def mpu9250_gyro_z(self): + return self.mpu6500.gyro[2] + + def mpu9250_gyro_values(self): + return self.mpu6500.gyro + + @property + def mpu9250_magnetic(self): + """X, Y, Z axis micro-Tesla (uT) as floats.""" + return self.ak8963.magnetic + + def mpu9250_magnetic_x(self): + return self.mpu9250_magnetic[0] + + def mpu9250_magnetic_y(self): + return self.mpu9250_magnetic[1] + + def mpu9250_magnetic_z(self): + return self.mpu9250_magnetic[2] + + def mpu9250_magnetic_values(self): + return self.mpu9250_magnetic + + # @property + def mpu9250_get_field_strength(self): + x=self.mpu9250_magnetic[0] + y=self.mpu9250_magnetic[1] + z=self.mpu9250_magnetic[2] + return (x**2+y**2+z**2)**0.5*1000 + + def mpu9250_heading(self): + x=self.mpu9250_magnetic[0] + y=self.mpu9250_magnetic[1] + z=self.mpu9250_magnetic[2] + a=math.atan(z/x) + b=math.atan(z/y) + xr=x*math.cos(a)+y*math.sin(a)*math.sin(b)-z*math.cos(b)*math.sin(a) + yr=x*math.cos(b)+z*math.sin(b) + return 60*math.atan(yr/xr) + + @property + def whoami(self): + return self.mpu6500.whoami + + def __enter__(self): + return self + + def __exit__(self, exception_type, exception_value, traceback): + pass + +class Compass: + RAD_TO_DEG = 57.295779513082320876798154814105 + + def __init__(self, sensor): + self.sensor = sensor + + def get_x(self): + return self.sensor.mpu9250_magnetic[0] + + def get_y(self): + return self.sensor.mpu9250_magnetic[1] + + def get_z(self): + return self.sensor.mpu9250_magnetic[2] + + def get_field_strength(self): + return self.sensor.mpu9250_get_field_strength() + + def heading(self): + from math import atan2 + xyz = self.sensor.mpu9250_magnetic + return int(((atan2(xyz[1], xyz[0]) * Compass.RAD_TO_DEG) + 180) % 360) + + def calibrate(self): + import matrix16x8 + mp_i2c=SoftI2C(scl = Pin(7), sda = Pin(6), freq = 400000) + mp_matrix = matrix32x12.Matrix(mp_i2c) + if self.is_calibrate() is False: + # print('The calibration need to shaking in the air (e.g. 8 or 0) and waiting for a moment') + print('First write 8 or 0 in the air with the board about 30 seconds, and then try to rotate the board in different direnctions several times.') + mp_matrix.pixel(7, 3, 1) + #mp_matrix.blink_rate(2) + l1=0 + l2=0 + l3=0 + l4=0 + l5=0 + l6=0 + l7=0 + l8=0 + while True: + x = self.sensor.mpu6500.acceleration()[0] + y = self.sensor.mpu6500.acceleration()[1] + z = self.sensor.mpu6500.acceleration()[2] + a=(x**2+y**2+z**2)**0.5 + if z > 0: + if x > 0 and y > 0 and a >= 12: + l1=l1 + 1 + if x > 0 and y < 0 and a >= 12: + l2=l2 + 1 + if x < 0 and y > 0 and a >= 12: + l3=l3 + 1 + if x < 0 and y < 0 and a >= 12: + l4=l4 + 1 + if z < 0: + if x > 0 and y > 0 and a >= 12: + l5=l5 + 1 + if x > 0 and y < 0 and a >= 12: + l6=l6 + 1 + if x < 0 and y > 0 and a >= 12: + l7=l7 + 1 + if x < 0 and y < 0 and a >= 12: + l8=l8 + 1 + if l1 >= 2: + mp_matrix.pixel(7, 0, 1) + mp_matrix.pixel(8, 0, 1) + mp_matrix.pixel(9, 1, 1) + if l2 >= 2: + mp_matrix.pixel(10, 2, 1) + mp_matrix.pixel(10, 3, 1) + if l3 >= 2: + mp_matrix.pixel(10, 4, 1) + mp_matrix.pixel(10, 5, 1) + if l4 >= 2: + mp_matrix.pixel(9, 6, 1) + mp_matrix.pixel(8, 7, 1) + if l5 >= 2: + mp_matrix.pixel(7, 7, 1) + mp_matrix.pixel(6, 7, 1) + if l6 >= 2: + mp_matrix.pixel(5, 6, 1) + mp_matrix.pixel(4, 5, 1) + if l7 >= 2: + mp_matrix.pixel(4, 4, 1) + mp_matrix.pixel(4, 3, 1) + if l8 >= 2: + mp_matrix.pixel(4, 2, 1) + mp_matrix.pixel(5, 1, 1) + mp_matrix.pixel(6, 0, 1) + if l1>=2 and l2>=2 and l3>=2 and l4>=2 and l5>=2 and l6>=2 and l7>=2 and l8>=2: + break + else: + self.sensor.ak8963.calibrate() + with open("compass_cfg.py", "w") as f: + f.write('\n_offset = ' + str(self.sensor.ak8963._offset) + '\n_scale = ' + str(self.sensor.ak8963._offset)) + else: + print('The calibration configuration already exists. If you need to recalibrate, enter os.remove("compass_cfg.py") in repl and restart') + try: + import compass_cfg + self.sensor.ak8963._offset = compass_cfg._offset + self.sensor.ak8963._scale = compass_cfg._scale + except Exception as e: + print('compass_cfg error! delete it, please.') + with open("compass_cfg.py") as f: + for line in f: + print(line) + + def is_calibrate(self): + try: + import compass_cfg + return True + except Exception as e: + return False + + def reset_calibrate(self): + import os + os.remove("compass_cfg.py") diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ms32006.py b/mixly/boards/default_src/micropython/origin/build/lib/ms32006.py new file mode 100644 index 00000000..fc1cc71a --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ms32006.py @@ -0,0 +1,137 @@ +""" +MS32006 + +Micropython library for the MS32006 step diever +======================================================= +#Changed from circuitpython to micropython 20211206 +#Fix register read / write bug 20211215 +dahanzimin From the Mixly Team + +""" +import time +from micropython import const + + +MS32006_REG_RESET = const(0x00) #复位 +MS32006_FCLK = const(25000000) #芯片输入时钟选择,此参数与运动速度有关。 范围是:5-30MHZ + +ADDRESS_A = 0x10 +ADDRESS_B = 0x18 +MOT_FULL = 0 +MOT_HALF = 1 +MOT_A = 0 +MOT_B = 4 +MOT_N = 0 +MOT_CW = 1 +MOT_CCW = 2 +MOT_P = 3 +class MS32006: + + _buffer = bytearray(2) + + def __init__(self, i2c_bus,addr=ADDRESS_A,mode=MOT_FULL): + self._device = i2c_bus + self._address = addr + self.reset() + self.mode=mode + + + def _read_u8(self, reg): + return self._device.readfrom_mem(self._address, reg, 1)[0] + + def _write_u8(self, reg, val): + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def reset(self): + self._write_u8(MS32006_REG_RESET,0x00) + time.sleep(0.1) + self._write_u8(MS32006_REG_RESET,0xC1) + + def move(self,moto,mot_dir,mot_pps,mot_step): + readstate_0H = self._read_u8(0x00) + readstate_9H = self._read_u8(0x09) + speed_data=MS32006_FCLK//mot_pps//128 #设置速度 xx pps 128是固定参数 + + if speed_data<32: #限定转速 + speed_data=32 + elif speed_data>16383: + speed_data=16383 + + mot_speed_l=speed_data&0x00ff #取低8位 + mot_speed_h=speed_data//0x100 #取高6位 + + if self.mode==MOT_FULL: #设置整步、半步驱动模式 + mot_speed_h|=0x80 + else: + mot_speed_h&=0x7f + + if mot_step>2047: + raise AttributeError("Reach the set upper limit, up to 2047 step") + + mot_step_l=mot_step&0x00ff + mot_step_h=mot_step//0x100 + mot_step_h|=0x80 + + if mot_dir==MOT_CW: + mot_step_h&=0xBF + else: + mot_step_h|=0x40 + self._write_u8(0x01+moto,mot_speed_l) + self._write_u8(0x02+moto,mot_speed_h) + self._write_u8(0x03+moto,mot_step_l) + self._write_u8(0x04+moto,mot_step_h) + + if moto==MOT_A: + self._write_u8(0x00, readstate_0H&0xfb) + self._write_u8(0x09, readstate_9H|0x80) + else: + self._write_u8(0x00, readstate_0H&0xfd) + self._write_u8(0x09, readstate_9H|0x40) + + def close(self,moto): #停止并关闭输出 + if moto==MOT_A: + self._write_u8(0x04,0x00) + else: + self._write_u8(0x08,0x00) + + def stop(self,moto): #此停止函数,强制让电机停止 + readstate = self._read_u8(0x00) + if moto==MOT_A: + self._write_u8(0x00,readstate|0x04) + else: + self._write_u8(0x00,readstate|0x02) + + def readstep(self,moto): #读取电机运动步数 + if moto==MOT_A: + rdb =self._read_u8(0x0b) + rdc =self._read_u8(0x0c) + else: + rdb =self._read_u8(0x0d) + rdc =self._read_u8(0x0e) + return (rdb*0x100+rdc)&0xfff + + def readbusy(self,moto): #读取电机缓存是否有数据 + if moto==MOT_A: + busy =(self._read_u8(0x0b)>>6)&1 + else: + busy =(self._read_u8(0x0d)>>6)&1 + return bool(busy) + + def readwork(self,moto): #读取电机是否在运行 + if moto==MOT_A: + busy =(self._read_u8(0x0b)>>4)&1 + else: + busy =(self._read_u8(0x0d)>>4)&1 + return bool(busy) + + def dc_motor(self,state,speed=100): #直流电机驱动 + if (state==MOT_CW) | (state==MOT_CCW) : + speed_st=speed*127//100 |0x80 + self._write_u8(0x0A,speed_st) + + readstate = self._read_u8(0x09) & 0xA0 + state_st=(state<<2) | 0X03 | readstate + self._write_u8(0x09,state_st) + + + \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ms5611.py b/mixly/boards/default_src/micropython/origin/build/lib/ms5611.py new file mode 100644 index 00000000..ce3f48e1 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ms5611.py @@ -0,0 +1,81 @@ +import utime +from micropython import const + +_MS5611_ADDR = const(0x77) +_CMD_ADC_READ = const(0x00) +_CMD_RESET = const(0x1E) +_CMD_CONVERT_D1 = const(0x40) +_CMD_CONVERT_D2 = const(0x50) +_CAL_DATA_C1 = const(0xA2) +_CAL_DATA_C2 = const(0xA4) +_CAL_DATA_C3 = const(0xA6) +_CAL_DATA_C4 = const(0xA8) +_CAL_DATA_C5 = const(0xAA) +_CAL_DATA_C6 = const(0xAC) + +# Oversampling settings +OSR={"OSR_256":0, "OSR_512":2, "OSR_1024":4, "OSR_2048":6, "OSR_4096":8} + +class MS5611: + def __init__(self, i2c_bus, addr=_MS5611_ADDR, osr='OSR_4096'): + self._device = i2c_bus + self._address = addr + self._wreg(_CMD_RESET) + utime.sleep_ms(50) + + self.c1 = self._rreg(_CAL_DATA_C1, 2) + self.c2 = self._rreg(_CAL_DATA_C2, 2) + self.c3 = self._rreg(_CAL_DATA_C3, 2) + self.c4 = self._rreg(_CAL_DATA_C4, 2) + self.c5 = self._rreg(_CAL_DATA_C5, 2) + self.c6 = self._rreg(_CAL_DATA_C6, 2) + self.pressure_cmd_rate = _CMD_CONVERT_D1 + OSR[osr] + self.temp_cmd_rate = _CMD_CONVERT_D2 + OSR[osr] + + def _wreg(self, val): + '''Write memory address''' + self._device.writeto(self._address, bytes([val])) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return int.from_bytes(self._device.readfrom_mem(self._address, reg, nbytes), 'big') + + @property + def getdata(self): + '''处理获取数据''' + self._wreg(self.pressure_cmd_rate) + utime.sleep_ms(15) + D1 = self._rreg(_CMD_ADC_READ, 3) + + self._wreg(self.temp_cmd_rate) + utime.sleep_ms(15) + D2 = self._rreg(_CMD_ADC_READ, 3) + + dT = D2 - self.c5 * 2 ** 8 + TEMP = 2000 + dT * self.c6 / 2 ** 23 + OFF = self.c2 * 2 ** 16 + dT * self.c4 / 2 ** 7 + SENS = self.c1 * 2 ** 15 + dT * self.c3 / 2 ** 8 + + if TEMP < 2000: + T2 = dT * dT / 2 ** 31 + OFF2 = 5 * (TEMP - 2000) ** 2 / 2 + SENS2 = 5 * (TEMP - 2000) ** 2 / 4 + if TEMP < -1500: + OFF2 = OFF2 + 7 * (TEMP + 1500) ** 2 + SENS2 = SENS2 + 11 * (TEMP + 1500) ** 2 / 2 + TEMP = TEMP - T2 + OFF = OFF - OFF2 + SENS = SENS - SENS2 + + P = (D1 * SENS / 2 ** 21 - OFF) / 2 ** 15 + H = (1 - (P / 101325) ** (1 / 5.255)) * 44330 + return round(P / 100, 2), round(TEMP / 100, 2), round(H, 2) + + def pressure(self): + return self.getdata[0] + + def temperature(self): + return self.getdata[1] + + def altitude(self, reference=1013.25): + return (pow((reference / 33.8639), 0.190255) - pow((self.getdata[0] / 33.8639), 0.190255)) / 0.000013125214 diff --git a/mixly/boards/default_src/micropython/origin/build/lib/msa301.py b/mixly/boards/default_src/micropython/origin/build/lib/msa301.py new file mode 100644 index 00000000..c677e1cb --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/msa301.py @@ -0,0 +1,57 @@ +""" +MSA301 + +Micropython library for the MSA301 Accelerometer +======================================================= +#Preliminary composition 20220817 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +MSA301_ADDRESS = const(0x26) +MSA301_REG_DEVICE_ID = const(0x01) +MSA301_REG_DATA = const(0x02) +MSA301_REG_ODR = const(0x10) +MSA301_REG_POWERMODE = const(0x11) +MSA301_REG_RESRANGE = const(0x0F) + +class MSA301: + def __init__(self, i2c_bus, front=False): + self._device = i2c_bus + self._address = MSA301_ADDRESS + self._front = front + if self._chip_id() != 0x13: + raise AttributeError("Cannot find a MSA301") + + self._wreg(MSA301_REG_ODR,0X09) #RATE_500_HZ + self._wreg(MSA301_REG_POWERMODE,0X12) #NORMAL & WIDTH_250_HZ + self._wreg(MSA301_REG_RESRANGE,0X02) #RESOLUTION_14_BIT & RANGE_8_G + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _chip_id(self): + return self._rreg(MSA301_REG_DEVICE_ID) + + def u2s(self,n): + return n if n < (1 << 7) else n - (1 << 8) + + def acceleration(self): + data_reg=self._rreg(MSA301_REG_DATA,6) + x_acc=((self.u2s(data_reg[1])<<8|data_reg[0])>>2)/1024.0 + y_acc=((self.u2s(data_reg[3])<<8|data_reg[2])>>2)/1024.0 + z_acc=((self.u2s(data_reg[5])<<8|data_reg[4])>>2)/1024.0 + return (-y_acc,-x_acc,z_acc) if self._front else (y_acc,-x_acc,z_acc) + + def eulerangles(self,upright=False): + x,y,z=self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/music.py b/mixly/boards/default_src/micropython/origin/build/lib/music.py new file mode 100644 index 00000000..7528ad36 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/music.py @@ -0,0 +1,174 @@ +""" +Music buzzer + +Micropython library for the Music buzzer +======================================================= +@dahanzimin From the Mixly Team +""" +import _thread, gc +from time import sleep_ms +from machine import Pin, PWM + +normal_tone = { + 'A1': 55, 'B1': 62, 'C1': 33, 'D1': 37, 'E1': 41, 'F1': 44, 'G1': 49, + 'A2': 110, 'B2': 123, 'C2': 65, 'D2': 73, 'E2': 82, 'F2': 87, 'G2': 98, + 'A3': 220, 'B3': 247, 'C3': 131, 'D3': 147, 'E3': 165, 'F3': 175, 'G3': 196, + 'A4': 440, 'B4': 494, 'C4': 262, 'D4': 294, 'E4': 330, 'F4': 349, 'G4': 392, + 'A5': 880, 'B5': 988, 'C5': 523, 'D5': 587, 'E5': 659, 'F5': 698, 'G5': 784, + 'A6': 1760, 'B6': 1976, 'C6': 1047, 'D6': 1175, 'E6': 1319, 'F6': 1397, 'G6': 1568, + 'A7': 3520, 'B7': 3951, 'C7': 2093, 'D7': 2349, 'E7': 2637, 'F7': 2794, 'G7': 3135, + 'A8': 7040, 'B8': 7902, 'C8': 4186, 'D8': 4699, 'E8': 5274, 'F8': 5588, 'G8': 6271, + 'A9': 14080, 'B9': 15804 } + +Letter = 'ABCDEFG#R' + +class MIDI(): + def __init__(self, pin, volume=100, invert=0, pa_ctrl=None): + self.reset() + self._invert = invert + self._pin = pin + self._volume = volume + self._play = False + self._over = True + self._pwm = None + self._pa_ctrl = pa_ctrl + + def set_volume(self, volume): + if not 0 <= volume <= 100: + raise ValueError("Volume value is in the range: 0-100") + self._volume=volume + + def set_tempo(self, ticks=4, bpm=120): + self.ticks = ticks + self.bpm = bpm + self.beat = 60000 / self.bpm / self.ticks + + def set_octave(self, octave=4): + self.octave = octave + + def set_duration(self, duration=4): + self.duration = duration + + def get_tempo(self): + return (self.ticks, self.bpm) + + def get_octave(self): + return self.octave + + def get_duration(self): + return self.duration + + def reset(self): + self.set_duration() + self.set_octave() + self.set_tempo() + + def parse(self, tone, dict): + time = self.beat * self.duration + pos = tone.find(':') + if pos != -1: + time = self.beat * int(tone[(pos + 1):]) + tone = tone[:pos] + freq, tone_size = 1, len(tone) + if 'R' in tone: + freq = 400000 + elif tone_size == 1: + freq = dict[tone[0] + str(self.octave)] + elif tone_size == 2: + freq = dict[tone] + self.set_octave(tone[1:]) + return int(freq), int(time) + + def midi(self, tone): + pos = tone.find('#') + if pos != -1: + return self.parse(tone.replace('#', ''), normal_tone) + pos = tone.find('B') + if pos != -1 and pos != 0: + return self.parse(tone.replace('B', ''), normal_tone) + return self.parse(tone, normal_tone) + + def set_default(self, tone): + pos = tone.find(':') + if pos != -1: + self.set_duration(int(tone[(pos + 1):])) + tone = tone[:pos] + + def play(self, tune, duration=None, pa_delay=100): + if self._pa_ctrl: self._pa_ctrl(1, pa_delay) + self._pwm = PWM(Pin(self._pin), duty=1023 if self._invert else 0) + self._play = True + self._over = False + if duration is None: + self.set_default(tune[0]) + else: + self.set_duration(duration) + for tone in tune: + tone = tone.upper() + if not self._play: + break + if tone[0] not in Letter: + continue + midi = self.midi(tone) + if self._play: self._pwm.duty((1023-self._volume) if self._invert else self._volume) + if self._play: self._pwm.freq(midi[0]) + sleep_ms(midi[1]) + if self._play: self._pwm.freq(400000) + sleep_ms(1) + if self._pa_ctrl: self._pa_ctrl(0, 0) + self._pwm.deinit() + sleep_ms(10) + self._over = True + + def play_thread(self, tune, duration=None, pa_delay=100): + self._play = False + while not self._over: + sleep_ms(10) + if not self._play: + gc.collect() + _thread.start_new_thread(self.play, (tune, duration, pa_delay)) + sleep_ms(100) + + def pitch(self, freq, pa_delay=100): + if self._pa_ctrl: self._pa_ctrl(1, pa_delay) + self._pwm = PWM(Pin(self._pin)) + self._pwm.duty((1023-self._volume) if self._invert else self._volume) + self._pwm.freq(int(freq)) + + def pitch_time(self, freq, delay, pa_delay=100): + if self._pa_ctrl: self._pa_ctrl(1, pa_delay) + self._pwm = PWM(Pin(self._pin)) + self._pwm.duty((1023-self._volume) if self._invert else self._volume) + self._pwm.freq(int(freq)) + sleep_ms(delay) + if self._pa_ctrl: self._pa_ctrl(0, 0) + self._pwm.deinit() + sleep_ms(10) + + def stop(self): + self._play = False + if self._pa_ctrl: self._pa_ctrl(0, 0) + if self._pwm: self._pwm.deinit() + sleep_ms(10) + + DADADADUM=['r4:2','g','g','g','eb:8','r:2','f','f','f','d:8'] + ENTERTAINER=['d4:1','d#','e','c5:2','e4:1','c5:2','e4:1','c5:3','c:1','d','d#','e','c','d','e:2','b4:1','d5:2','c:4'] + PRELUDE=['c4:1','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e','c4','d','g','d5','f','g4','d5','f','c4','d','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','c4','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e'] + ODE=['e4','e','f','g','g','f','e','d','c','c','d','e','e:6','d:2','d:8','e:4','e','f','g','g','f','e','d','c','c','d','e','d:6','c:2','c:8'] + NYAN=['f#5:1','g#','c#:1','d#:2','b4:1','d5:1','c#','b4:2','b','c#5','d','d:1','c#','b4:1','c#5:1','d#','f#','g#','d#','f#','c#','d','b4','c#5','b4','d#5:2','f#','g#:1','d#','f#','c#','d#','b4','d5','d#','d','c#','b4','c#5','d:2','b4:1','c#5','d#','f#','c#','d','c#','b4','c#5:2','b4','c#5','b4','f#:1','g#','b:2','f#:1','g#','b','c#5','d#','b4','e5','d#','e','f#','b4:2','b','f#:1','g#','b','f#','e5','d#','c#','b4','f#','d#','e','f#','b:2','f#:1','g#','b:2','f#:1','g#','b','b','c#5','d#','b4','f#','g#','f#','b:2','b:1','a#','b','f#','g#','b','e5','d#','e','f#','b4:2','c#5'] + RINGTONE=['c4:1','d','e:2','g','d:1','e','f:2','a','e:1','f','g:2','b','c5:4'] + FUNK=['c2:2','c','d#','c:1','f:2','c:1','f:2','f#','g','c','c','g','c:1','f#:2','c:1','f#:2','f','d#'] + BLUES=['c2:2','e','g','a','a#','a','g','e','c2:2','e','g','a','a#','a','g','e','f','a','c3','d','d#','d','c','a2','c2:2','e','g','a','a#','a','g','e','g','b','d3','f','f2','a','c3','d#','c2:2','e','g','e','g','f','e','d'] + BIRTHDAY=['c4:4','c:1','d:4','c:4','f','e:8','c:3','c:1','d:4','c:4','g','f:8','c:3','c:1','c5:4','a4','f','e','d','a#:3','a#:1','a:4','f','g','f:8'] + WEDDING=['c4:4','f:3','f:1','f:8','c:4','g:3','e:1','f:8','c:4','f:3','a:1','c5:4','a4:3','f:1','f:4','e:3','f:1','g:8'] + FUNERAL=['c3:4','c:3','c:1','c:4','d#:3','d:1','d:3','c:1','c:3','b2:1','c3:4'] + PUNCHLINE=['c4:3','g3:1','f#','g','g#:3','g','r','b','c4'] + PYTHON=['d5:1','b4','r','b','b','a#','b','g5','r','d','d','r','b4','c5','r','c','c','r','d','e:5','c:1','a4','r','a','a','g#','a','f#5','r','e','e','r','c','b4','r','b','b','r','c5','d:5','d:1','b4','r','b','b','a#','b','b5','r','g','g','r','d','c#','r','a','a','r','a','a:5','g:1','f#:2','a:1','a','g#','a','e:2','a:1','a','g#','a','d','r','c#','d','r','c#','d:2','r:3'] + BADDY=['c3:3','r','d:2','d#','r','c','r','f#:8'] + CHASE=['a4:1','b','c5','b4','a:2','r','a:1','b','c5','b4','a:2','r','a:2','e5','d#','e','f','e','d#','e','b4:1','c5','d','c','b4:2','r','b:1','c5','d','c','b4:2','r','b:2','e5','d#','e','f','e','d#','e'] + BA_DING=['b5:1','e6:3'] + WAWAWAWAA=['e3:3','r:1','d#:3','r:1','d:4','r:1','c#:8'] + JUMP_UP=['c5:1','d','e','f','g'] + JUMP_DOWN=['g5:1','f','e','d','c'] + POWER_UP=['g4:1','c5','e4','g5:2','e5:1','g5:3'] + POWER_DOWN=['g5:1','d#','c','g4:2','b:1','c5:3'] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/mxc6655xa.py b/mixly/boards/default_src/micropython/origin/build/lib/mxc6655xa.py new file mode 100644 index 00000000..c8884ae5 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/mxc6655xa.py @@ -0,0 +1,91 @@ +""" +MXC6655XA + +Micropython library for the MXC6655XA Accelerometer +======================================================= +#Changed from circuitpython to micropython 20220224 +#Format unified 20220623 + +dahanzimin From the Mixly Team +""" +import time +from math import atan,sqrt,degrees +from micropython import const + +MXC6655XA_ADDRESS = const(0x15) +MXC6655XA_REG_DATA = const(0x03) +MXC6655XA_REG_CTRL = const(0x0D) +MXC6655XA_REG_DEVICE_ID = const(0x0E) +MXC6655XA_CMD_8G_POWER_ON = const(0x40) +MXC6655XA_CMD_4G_POWER_ON = const(0x20) +MXC6655XA_CMD_2G_POWER_ON = const(0x00) + +_Range = ( + MXC6655XA_CMD_2G_POWER_ON, # 2g + MXC6655XA_CMD_4G_POWER_ON, # 4g + MXC6655XA_CMD_8G_POWER_ON, # 8g +) + +_Range_X = ( + 1024, # 2g + 512, # 4g + 256, # 8g +) + +MXC6655XA_T_ZERO =25 +MXC6655XA_T_SENSITIVITY =0.586 + +class MXC6655XA: + + def __init__(self,i2c_bus,set_range=2, front=False): + self._device = i2c_bus + self._address = MXC6655XA_ADDRESS + self._range = set_range #default 8g range + self._front = front + + if self._chip_id() != 0x02: + raise AttributeError("Cannot find a MXC6655XA") + self._Enable() #star + #time.sleep(0.3) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(MXC6655XA_REG_DEVICE_ID) + + def _Enable(self): + self._wreg(MXC6655XA_REG_CTRL,_Range[self._range]) + + def u2s(self,n): + return n if n < (1 << 7) else n - (1 << 8) + + @property + def getdata(self): + data_reg=self._rreg(MXC6655XA_REG_DATA,7) + x_acc=float((self.u2s(data_reg[0])<<8|data_reg[1])>>4)/_Range_X[self._range] + y_acc=float((self.u2s(data_reg[2])<<8|data_reg[3])>>4)/_Range_X[self._range] + z_acc=float((self.u2s(data_reg[4])<<8|data_reg[5])>>4)/_Range_X[self._range] + t_acc=float(self.u2s(data_reg[6]))*MXC6655XA_T_SENSITIVITY + MXC6655XA_T_ZERO + return (-y_acc,-x_acc,z_acc,round(t_acc,1)) if self._front else (y_acc,-x_acc,z_acc,round(t_acc,1)) + + def acceleration(self): + return self.getdata[0:3] + + def strength(self): + from math import sqrt + return sqrt(self.getdata[0]**2+self.getdata[1]**2+self.getdata[2]**2) + + def temperature(self): + return self.getdata[3] + + def eulerangles(self,upright=False): + x,y,z=self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ns9300.py b/mixly/boards/default_src/micropython/origin/build/lib/ns9300.py new file mode 100644 index 00000000..3bd5a6e3 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ns9300.py @@ -0,0 +1,117 @@ +""" +NS9300 + +Micropython library for the NS9300(Music Player) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_PLAY_CTRL = const(0x04) +_PLAY_VOL = const(0x06) +_PLAY_INS = const(0x09) +_PLAY_MODE = const(0x0B) + +class NS9300: + def __init__(self, uart, delay=250): + self._uart = uart + self._delay = delay + self._uart.init(baudrate=9600, timeout_char=5) + if not self._chip_id(): + raise AttributeError("Cannot find a NS930x") + + def _wreg(self, cmd, data=b'\x00'): + '''Write memory address''' + _buf = bytearray([cmd, 255 - cmd, len(data)]) + data + eec = 0 + for i in range(len(_buf)): + eec += _buf[i] + _buf.append(eec & 0xFF) + #print("TX:", bytes(_buf), len(_buf)) + self._uart.write(_buf) + + def _rreg(self, cmd): + '''read memory address''' + time.sleep_ms(self._delay) + if self._uart.any(): + _buf = self._uart.read() + #print("RX:", _buf, len(_buf)) + if _buf[0] == 0xAA and _buf[1] == 0x55: + raise OSError("Play Error", _buf[4]) + elif _buf[0] == cmd and _buf[0] == (255 - _buf[1]): + #eec = 0 + #for i in range(len(_buf) - 1): + #eec += _buf[i] + #if (eec & 0xFF) == _buf[-1]: + return _buf[3:3 + _buf[2]] + + def _chip_id(self): + '''复位指令有问题,暂停止播放态处理''' + for _ in range(10): + self._wreg(_PLAY_CTRL, b'\x03') + if self._rreg(_PLAY_CTRL): + return True + + def _ascll(self, data): + '''获取ASCLL字节,剔除中文''' + _strs='' + for char in data: + _strs += char if ord(char) <= 0xFF else "*" + return _strs.encode() + + def status(self, value=1): + """0已停止? 1播放中? 2已暂停?""" + return self.control(0) == value + + def control(self, value=0): + """0查询(0停止 1播放 2暂停) 1播放 2暂停 3停止 4上一曲 5下一曲 6总曲数 7当前曲""" + self._wreg(_PLAY_CTRL, (value if value <= 5 else value + 7).to_bytes(1, 'little')) + _dat = self._rreg(_PLAY_CTRL) + if _dat: + return _dat[1] if value <= 3 else _dat[1] << 8 | _dat[2] + + def play(self, value='m*.mp3'): + """int播放曲目 str播放文件(*省略,GBK编码MPY不支持)""" + if isinstance(value, int): + self._wreg(_PLAY_CTRL, b'\x06' + value.to_bytes(2, 'big')) + elif isinstance(value, str): + self._wreg(_PLAY_CTRL, b'\x07' + self._ascll(value)) + else: + raise ValueError("Input format error") + _dat = self._rreg(_PLAY_CTRL) + if _dat: + return _dat[1] << 8 | _dat[2] + + def insert(self, value='m*.mp3'): + """int播放曲目 str播放文件(*省略,GBK编码MPY不支持)""" + if isinstance(value, int): + self._wreg(_PLAY_INS, b'\x00\x02' + value.to_bytes(2, 'big')) + elif isinstance(value, str): + self._wreg(_PLAY_INS, b'\x01\x02' + self._ascll(value)) + else: + raise ValueError("Input format error") + time.sleep_ms(self._delay) + + def volume(self, value=None): + """None返回音量 int设置音量(0~30)""" + if value is None: + self._wreg(_PLAY_VOL, b'\x00') + _dat = self._rreg(_PLAY_VOL) + if _dat: + return _dat[1] + else: + value = min(30, max(0, value)) + self._wreg(_PLAY_VOL, b'\x01' + value.to_bytes(1, 'little')) + time.sleep_ms(self._delay) + + def mode(self, value=None): + """0全部循环 1单曲循环 2目录循环 3随机播放 4单曲停止 5顺序播放""" + if value is None: + self._wreg(_PLAY_MODE, b'\x00') + _dat = self._rreg(_PLAY_MODE) + if _dat: + return _dat[1] + else: + self._wreg(_PLAY_MODE, b'\x01' + value.to_bytes(1, 'little')) + time.sleep_ms(self._delay) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ntptime.py b/mixly/boards/default_src/micropython/origin/build/lib/ntptime.py new file mode 100644 index 00000000..cce0a4b0 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ntptime.py @@ -0,0 +1,46 @@ +import utime,gc +from machine import RTC +import usocket as socket +import ustruct as struct + +# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 +NTP_DELTA=3155673600 + +def time(host="pool.ntp.org", utc=28800, times=5): + for _ in range(times): + try: + NTP_QUERY = bytearray(48) + NTP_QUERY[0] = 0x1B + addr = socket.getaddrinfo(host, 123)[0][-1] + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.settimeout(1) + res = s.sendto(NTP_QUERY, addr) + msg = s.recv(48) + finally: + del addr + s.close() + gc.collect() + val = struct.unpack("!I", msg[40:44])[0] + return utime.gmtime(val - NTP_DELTA + utc) + except Exception as e: + error = e + utime.sleep(0.1) + raise OSError('Error fetching network time', error) + +# There's currently no timezone support in MicroPython, and the RTC is set in UTC time. +def settime(times): + if isinstance(times, str): + try: + val = eval(times) + if len(val) >= 6: + times=(val[0], val[1], val[2], val[3], val[4], val[5], 0) + else: + raise ValueError("Clock information format error") + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0)) + else: + raise ValueError("Settime needs a tuple of length 6~8") diff --git a/mixly/boards/default_src/micropython/origin/build/lib/object_picture.py b/mixly/boards/default_src/micropython/origin/build/lib/object_picture.py new file mode 100644 index 00000000..aae96ce1 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/object_picture.py @@ -0,0 +1,18 @@ +#Take the picture bytes in object_picture.py +#--dahanzimin From the Mixly Team + +Bomb=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x0e\x00\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x02\x00\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x03\x00\x80\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x80\x800\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x80\x80`\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x80\x80\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00A\x01\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00 \x04\x00\x00\x00\x00\x00\x00\x7f\x00\x00@\x11\x18\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x000\x00\x00\x00\x00\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x02\x80\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00#\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x7f\x00\x00\x00@\x00\x06\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x03\xf8\x00\x00\x00\x00\x7f\x00\x00\x06\x00\x00\x01\xf8\x00\x00\x00\x00\x7f\x00\x000\x08\x00\x03\xfc\x00\x00\x00\x00\x7f\x00\x01\xe0\x10\x00\x07\xfc\x00\x00\x00\x00\x7f\x00\x03\x00\x00\x80\x03\xff\xfe\x00\x00\x00\x7f\x00\x00\x000\x00\x03\xff\xff\xc0\x00\x00\x7f\x00\x00\x00 @\x01\xff\xfcp\x00\x00\x7f\x00\x00\x00@@\x03\xff\xff\x18\x00\x00\x7f\x00\x00\x00@@\x03\xff\xff\xcc\x00\x00\x7f\x00\x00\x00\xc0@\x07\xff\xff\xe6\x00\x00\x7f\x00\x00\x00\x00`\x0f\xff\xff\xf3\x00\x00\x7f\x00\x00\x00\x00 \x1f\xff\xff\xf1\x80\x00\x7f\x00\x00\x00\x00 ?\xff\xff\xf9\x80\x00\x7f\x00\x00\x00\x000?\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x000\x7f\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x10\x7f\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00?\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00?\xff\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xff\xff\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xff\xff\xfe\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xff\xfc\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xff\xff\xf8\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\xff\xe0\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xff\xc0\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Boom=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00p\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00X\x00\x0e\x00\x00\x00\x00\x7f\x00\x00\x00\x00x\x00\x16\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\x00:\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xae\x00g\x00\x00\x00\x00\x7f\x00\x00\x80\x01\x96\x00k\x00\x00\x00\x00\x7f\x00\x00\xc0\x01\xab\x81\xd5\x00\x00\x00\x00\x7f\x00\x00|\x03U\xff\xa5\x80\x00\x00\x00\x7f\x00\x00v\x06\xaa\xffU\x80\x00\x00\x00\x7f\x00\x00;\xfe\xa9~\xaa\xc3\x02\x00\x00\x7f\x00\x005\xfdU\x02U`\x0c\x00\x00\x7f\x00\x00\x1a\xaa\xaa\xaa\xaa\xb8x\x00\x04\x7f\x01\x00\x15T\xaa\xaa\xa9_\xf0\x00\x04\x7f\x00\x00\x19URT\xa6\xa2\xb0\x00\x00\x7f\x00\x00\x1a\xaa\xa9J\x95\x15`\x00\x00\x7f\x00\x00\x1a\xaa^\xb5n\xea`\x00\x00\x7f\x00\x009U_\x85\x1e\x15\xc0\x00\x00\x7f\x00\x00:\xaa\xae\xf8{\xea\xc0\x00\x00\x7f\x00\x00z\xaa\xad\x7f\xea\xea\xc0\x00\x00\x7f\x00\x01\xf5U.\xaf\xd5u\x80\x00\x00\x7f\x00\x01\xea\xaa\xadj\xaa\xeb\x80\x00\x00\x7f\x00\x0f\xea\xaa\xae\x95UU\x80\x00\x00\x7f\x07\xff\xaaUUe\xaa\xd5\xc0\x00\x00\x7f\x01\xfe\xaa\xa0\x0e\x9auj\xc0\x00\x00\x7f\x00:\xa9_\xf5\xe3\xea\xd5\xc0\x00\x00\x7f\x00\x0e*\xaf\xea\xdeuU`\x00\x00\x7f\x00\x03\x95V\xaa\x80j\xea\xb0\x00\x00\x7f\x00\x01\xea\xabU\x80j\xb5x\x00\x00\x7f\x00\x00\xea\xa9\xaa\x80*\xba\x9c\x00\x00\x7f\x00\x009U\xd5\x00:\xadW\x00\x00\x7f\x00\x00\x1dT\xd5\x00\x1a\xadW\xe0\x00\x7f\x00\x00\x1c\xa5\xd7\x00\x0e\xb7T\x1e\x00\x7f\x00\x00\x0fU\xdd\xc3\xfdOU\xf8\x00\x7f\x00\x00\x06\xaa\xa2\xe5V\xba\xa5\x80\x00\x7f\x00\x00\x03\xa9\xbe\xba\xaa\xb2W\x00\x00\x7f\x00\x00\x03U\xc1ZUj\xac\x00\x00\x7f\x10\x0c\x03\xab\xbfU\xaaj\xac\x00\x00\x7f\x00\x08\x03\xa5\xfb\xaaU\xaa\xa8\x00\x00\x7f\x00\x00\x03\xd5\xd4\xd5\xaar\x98\x00\x00\x7f\x00\x00\x03\x97UtU\xfdX\x1c\x00\x7f\x00\x00\x03\xa8\xaa{\x97\x92\xa8\x0c\x00\x7f\x00\x00\x03UUW\xf5UX\x00\x00\x7f\x00\x00\x07\xaa\xaa\xbd>\xaaL\x00\x00\x7f\x00\x00\x06>\x95YOS\xec\x00\x00\x7f\x00\x00\r\xff\xca\xba\xaa\xaf\xfa\x00\x00\x7f\x00\x00\x1f\x81\xf5Z\xab_\x0e\x00\x00\x7f\x00\x00\x1e\x00uIT\x9c\x03\x00\x00\x7f\x00\xc00\x00:\xaa\xaa\xb8\x00\x00\x00\x7f\x00\x00@\x00\x1a\xaa\xa2\x98\x00\x00\x04\x7f\x00\x00\x00\x00\tH\xfc\x98\x00\x00\x00\x7f\x00\x00\x00\x10\x0e\xab\xffp\x000\x00\x7f\x00\x00\x00\x00\x05O\x83P@\x10\x00\x7f\x00\x00\x00\x80\x06\xbe\x00\xd0 \x00\x00\x7f\x00\x04\x00\x00\x06\xb8\x00p\x00\x00\x00\x7f\x00\x10\x00\x00\x03p\x000\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xe0\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +DOOR_CLOSE=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x18\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x08\x00\x00\x01\x80\x00\x00\x18\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x11\x8c\x00\x00\x10\x08\x00\x009\x9e\x00\x00\x10\x08\x00\x00y\x9e\x00\x00\x10\x08\x00\x001\x8c\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x001\x8c\x00\x00\x10\x08\x00\x00y\x9e\x00\x00\x10\x08\x00\x009\x9e\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x18\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +DOOR_OPEN=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +DOOR_OPENING=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x08\xff\xff\xff\xff\xff\xff\x10\x08\x07\xff\xff\xff\xff\xe0\x10\x08\x00?\xff\xff\xfc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00?\xff\xff\xfc\x00\x10\x08\x07\xff\xff\xff\xff\xe0\x10\x08\xff\xff\xff\xff\xff\xff\x10\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +Fire=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x0f\x00\x00\x00\x00\x00\x7f\x00\x00\x03\x00\x00\x0f\x80\x00\x00\x01\x80\x7f\x00\x00\x03\x80\x00\x0f\x80\x00\x00\x03\x80\x7f\x00\x00\x03\xc0\x00\x0f\xc0\x00\x00\x07\x80\x7f\x00\x00\x07\xe0\x00\x1f\xc0\x00\x00\x07\x80\x7f\x00\x00\x07\xf0\x00\x1f\xc0\x00\x00\x07\xc0\x7f\x00\x00\x0f\xf0\x00?\xc0\x00\x00\x03\xc0\x7f\x00\x00\x0f\xf0\x00\x7f\xc0\x00\x00\x03\xe0\x7f\x00\x00\x1f\xf0\x00\xff\xc0\x00\x00\x03\xe0\x7f\x00\x00\x1f\xf0\x01\xff\xc0\x00\x00\x03\xf0\x7f\x00\x00\x1f\xf0\x07\xff\xc0\x00\x00\x03\xf8\x7f\x00\x00\x1f\xe0\x07\xff\xc0\x00\x00\x03\xfc\x7f\x00\x00\x1f\xe0\x0f\xff\xc0\x00\x00\x03\xfc\x7f\x00\x00\x1f\xe0\x0f\xff\xc0|\x00\x07\xfc\x7f\x00\x00\x0f\xe0\x1f\xff\xc3\xfe\x00\x07\xfc\x7f\x00\x00\x07\xc0\x1f\xff\x87\xfc\x00\x0f\xfc\x7f\x00\x00\x01\xc1\x1f\xff\x8f\xf8\x00?\xfc\x7f\x00\x00\x00\xe3\xbf\xef\x9f\xf8\x00\xff\xfc\x7f\x00\x00\x007\xbf\xef\xdf\xf8\x01\xff\xf8\x7f\x00\x00\x00\x0f\xbf\xdf\xff\xf0\x03\xff\xf8\x7f\x00\x00\x00\x1f\xdf\xdf\xfe\xf0\x07\xff\xf0\x7f\x10\x00\x00\x1f\xff\xdf\xff\xf0\x07\xff\x80\x7f\x18\x00\x00\x1f\xff\xaf\xfd\xf0\x0f\x80\x00\x7f\x1c\x00\x04\x1f\xff\xbf\xfb\xe0\x08\x00\x00\x7f\x1e\x00\x1e\x1f\xff\xdf\xfb\xe0\x00\x00\x00\x7f\x1f\x00>\x1f\xff\xaf\xfb\xe0\x00\x00\x00\x7f\x1f\x80~\x1f\xff\xaf\xf7\xe0\x00\x00\x00\x7f\x1f\xc0\x7f\x1f\xff\xaf\xeb\xe0~\x00\x00\x7f\x1f\xf0\x7f\x1f\xff\xd7\xf7\xe1\xfe\x00\x00\x7f\x1f\xf0\xff\x9f\xff\xab\xeb\xe7\xfc\x00\x00\x7f\x0f\xf8\xff\x8f\xbf\xab\xd7\xef\xf8\x00\x00\x7f\x0f\xf8\xff\xcf\xcf\xd5\xd7\xff\xf8\x0e\x00\x7f\x0f\xf8\xff\xef\xf5\xaa\xab\xffp\x7f\x00\x7f\x07\xfc\xff\xff\xf5UW\xfd\xf1\xfe\x00\x7f\x07\xfc\x7f\xff\xf5J\xab\xfe\xe3\xfc\x00\x7f\x03\xfc\x7f\xff\xfa\xf5U\xfd\xe7\xf8\x00\x7f\x01\xfc\x7f\xff\xfe\x9dU\xf5\xef\xf0\x00\x7f\x00\xfc\x7f\xff\xfdF\xaa\xea\xef\xf0\x00\x7f\x00\x1d\x7f\xb8\x00\x80\x7f\x00\xe0@\x00<\xf0\x1e\xef\xf8\x00\x80\x7f\x00x@\x07=\x00\x1f\xd7\xdc\x00\xc0\x7f\x000\xc0\x00\x10\x00\x00\x04\x00\x00\x08\x7f\x00\x02p\x00\x10\x00\x00\x04\x00\x00\x08\x7f' +Forest=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00~\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00z\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x07\xff\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x0f\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xff\xc0\x00\x00\x00\x00\x06\x00\x00\x7f\x00\x00\xfe\x00\x00\x00\x08\x00\x06\x00\x00\x7f\x00\x03\xff\x00\x00\x00\x0c\x89\x9d\x83\x00\x7f\x00\x0f\xff\x80\x00\x00\x07\x8d\x8b\x0e\x00\x7f\x00\x1f\xff\xc0\x00\x19a\xb0\x04\xc9\x80\x7f\x00?\xff\xf0\x00\x1b\x1aV\x1a\xb3\x90\x7f\x00\x7f\xff\xf0\x00\x06\xef\x84A\x14\x10\x7f\x00\xff\xff\xf8\x00\x1a`\xbb\x14\x8b\x10\x7f\x00\x01\xff\x04\x00P\x1b\x89d\xf4\x06\x7f\x00\x03\xff\x80\x00f\xe2\x91 d\x9e\x7f\x00\x0f\xff\xc0\x00\x018\xeb\xc7\xe0`\x7f\x00\x1f\xff\xf0\x00\xc4\xc1\xa8\xcc\xe1\xa8\x7f\x00?\xff\xf8\x04\xd6}\xb1\x15aL\x7f\x00\x7f\xff\xfe\x0e!/A\xe5`\xb0\x7f\x00\xff\xff\xff\x80\xd4'\x06 o0\x7f\x01\xfd\xff\xc1\xc35[\x06\xb0{\x00\x7f\x03\xe1\xff\xe0\x02\xb1\x13\xc1\xa0\xe10\x7f\x03\x87\xff\xf0\x01\xb0\x01\xe0\x03\xe6\xcc\x7f\x04\x1f\xff\xfc\x000\x03\xf8?\xc4Y\x7f\x00?\xff\xff\x80\x98\x07\xfc\xff\x81\x8b\xff\x00\x7f\xff\xff\xe3d\x1f\xfd\xfc\x01h\x7f\x01\xff\xff\xff\xc0\xe7\xfe?\xc0\x88L\x7f\x07\xff\xff\xfc\x0e\xa1\xf0\x0f\x84\x98\x0c\x7f\x1f\xf7\xff\xf0\x06X\xc0\x0f\x86\n\x00\x7f\x1f\xe7\xff\xf0\x03I\x80\x07\x81\x17\x00\x7f\x00\x07\xff\xf8\x03/@\x07\x81 0\x7f\x00\x0f\xff\xfc\x00\xb4@\x0f\x80\xcd\xe0\x7f\x00?\xff\xfe\x03\xe4\x80\x0f\x86\xc0(\x7f\x00\xff\xff\xff\x02c\x00?\x82\x87\xdc\x7f\x03\xff\xff\xff\x80\xc5\x07\xff\xfd\x8d@\x7f\x07\xe7\xff\xc7\xf0\x16?\xff\xff\xf9\xe0\x7f\x1c\x0f\xff\xe0x\x12\x7f\xfe\x0f\xf8\x80\x7f\x00?\xff\xf0\x00\x11\xff\xf8\x02\x84@\x7f\x00\x7f\xff\xfc\x00\x01\xff\xe0\x02D\xc0\x7f\x00\xff\xff\xfe\x00\x03\xff\x00\x02\xca\x80\x7f\x01\xff?\xff\x80\x07\xfe\x00\x00\x19p\x7f\x03\xfc;\xff\xe0\x07\xfc\x00\x00\x13 \x7f\x0f\xf08\xff\xf8\x0f\xf8\x00\x00\x02\xc0\x7f\x7f\x008\x0f\xff\x1f\xf8\x00\x00\x02\xc0\x7f\x00\x008\x00\x00\x1f\xf8\x00\x00\x00\x00\x7f\x00\x008\x00\x00?\xf8\x00\x00\x00\x00\x7f\x00\x008\x00\x0e\x7f\xf9\x00\x00\x00\x00\x7f\x00\x008\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" +Lightning=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xf0\x18\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xff\xa0\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xff@\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xfe\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xfd\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfb\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfa\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xe8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff`\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfe\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfc\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xf9\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xfa\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xec\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xd8\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xfe\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xfe\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xf8\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xf0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Light_off=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xd5p\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07J\xb8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1c\xb5\\\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1bEV\x00\x00\x00\x00\x7f\x00\x00\x00\x004\n\xab\x00\x00\x00\x00\x7f\x00\x00\x00\x00tUU\x00\x00\x00\x00\x7f\x00\x00\x00\x00h\xaa\xab\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd1UU\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xa2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xa5UU@\x00\x00\x00\x7f\x00\x00\x00\x01\xd2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xa5UU@\x00\x00\x00\x7f\x00\x00\x00\x01\xaa\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UU\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UT\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UW\x80\x00\x00\x00\x7f\x00\x00\x00\x00j\xaa\xa9\x80\x00\x00\x00\x7f\x00\x00\x00\x00eUW\x00\x00\x00\x00\x7f\x00\x00\x00\x00=US\x00\x00\x00\x00\x7f\x00\x00\x00\x002\xaa\xae\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1dUV\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xac\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rU\\\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0e\xaa\xa8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05UX\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\xb8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x90\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06Up\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xaa\xb0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xaa\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x83\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Light_on=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xc0\x00\x0c\x00\x02\x00\x00\x00\x7f\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x0c\x00\x00\x00\x7f\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x7f\x00\x00\x00\x0c\x00\x1e\x000\x00\x00\x00\x7f\x00\x00\x00\x06\x00\xff\xc0`\x00\x00\x00\x7f\x00\x00\x00\x02\x03\x80p\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x100\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x000\xe0\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00a\x80\x01\x00\x00\x00\x00\x7f\x00\x00\x00\x00B\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xc6\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x84\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x8c\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\x8c\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x01\x88\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x00\x00@\xfe\x00\x00\x7f\x00\x00\x7f\xc1\x80\x00\x00A\xfe\x00\x00\x7f\x00\x00\x00\x00\x80\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00@\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x01\x00\x00\x00\x00\x7f\x00\x00\x00\x00 \x00\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x00\x02\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x10\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x04\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x08\x00\x0c\x0c\x00\x00\x00\x7f\x00\x00\x00\x18\x0c\x00\x08\x06\x00\x00\x00\x7f\x00\x00\x000\x04\x00\x08\x03\x00\x00\x00\x7f\x00\x00\x00`\x04\x00\x18\x01\x80\x00\x00\x7f\x00\x00\x00\xc0\x06\x00\x10\x00\xc0\x00\x00\x7f\x00\x00\x01\x80\x06\x00\x10\x00`\x00\x00\x7f\x00\x00\x01\x00\x02\x000\x00 \x00\x00\x7f\x00\x00\x00\x00\x02\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x83\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Night=b'P4\n89 64\n\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\x7f\xff\xff\xff\xfe\x00\x7f\xff\xdf\xff\xff\xf7\xdf\xff\xff\xff\xe0\x00?\xff\xff\xff\xff\xef\xff\xff\xff\xff\x80\x01\xff\xff\xff\xff\x7f\xff\xef\xff\xff\xfe\x00\x07\xff\xff\xff\xff?\xdf\xff\xff\xff\xfc\x00\x0f\xff\xff\xff\xfe\x1f\xff\xff\xff\xff\xf8\x00?\xff\x87\xff\xfe?\xdf\xff\xff\xff\xf0\x00\x7f\xff\xcf\xff\xfe?\xff\xef\xff\xff\xe0\x00\xff\xff\xcf\xff\xff\xff\xef\xdf\xff\xff\xc0\x01\xff\xff\xff\xff\xff\xff\xfb\xbf\xff\xff\x80\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xf9\xff\xff\xff\xff\xff\xfc\x00\x0f\xff\xff\xff\xe0?\xff\xcf\xff\xff\xfc\x00\x1f\xff\xff\xff\xe0?\xff\x87\xff\xff\xfc\x00\x1f\xff\xff\xff\xf0\x7f\xff\x8f\xff\xff\xfc\x00\x1f\xff\xff\xff\xf0\x7f\xff\xcf\xff\xff\xfc\x00\x1f\xff\xff\xff\xf2\x7f\xbf\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xbf\xff\xff\xff\xf8\x00?\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xf5\xfb\xff\xff\xff\xf9\xff\xff\xfc\x00\x1f\xff\xee\xfb\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xee\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xf5\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\x80\x03\xff\xef\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x01\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xf0\x00\x7f\xff\xfc?\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xfe\x00\x1f\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xff\x00\x0f\xff\xe0\x07\xff\xff\xff\xbf\xff\xff\xff\xc0\x03\xff\xf0\x0f\xff\xf7\xff\x0f\xff\xff\xff\xf8\x00\x7f\xf8\x0f\xff\xff\xff\x1f\xff\xff\xff\xff\x83\xff\xf0\x0f\xff\xff\xff\x1f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf3\xcf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x0f\xff\xff\xfd\x7f\xff\xf1\xff\xff\xff\xff\xf8\x1f\xff\xff\xfb\xbf\xff\xf9\xff\xff\xff\xff\xfc?\xff\xff\xfb\xbf?\xff\xff\xff\xff\xff\xfc\x1f\xff\xff\xfd\x7f?\xff\xff\xff\xff\xff\xfd\x9f\xff\xff\xff\xff?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Pirate=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfb\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xf8\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfe`\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xb8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xd8\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xec\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xee\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf6\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf6\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xf9\xff\xe7\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xc0\x7f\x80\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xc0?\x00\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00?\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00?\xc0?\x00\xff\x00\x00\x00\x7f\x00\x00\x00?\xe0s\x81\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xf1\xf1\xe3\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xe1\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xe0\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\x7f\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\x7f\xc0\x00\x00\x00\x7f\x00\x00\xf0\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\xf0\x00\xff\xff\xff\x80\x00\xf0\x00\x7f\x00\x00\xf8\x00\x07\xff\xf8\x00\x01\xf0\x00\x7f\x00\x00\xf8\x00\x07\xff\xf8\x00\x03\xf0\x00\x7f\x00\x01\xff\x00\x07\xf7\xf8\x00\x07\xe0\x00\x7f\x00\x03\xff\xe0\x06s\x98\x00?\xf0\x00\x7f\x00\x03\xff\xfe\x00s\x98\x01\xff\xf8\x00\x7f\x00\x07\xff\xff\xc0!\x00\x1f\xff\xfc\x00\x7f\x00\x03\xf1\xff\xf8\x00\x01\xff\xf1\xfc\x00\x7f\x00\x03\xf0?\xff\x00\x0f\xff\x81\xf8\x00\x7f\x00\x01\xe0\x07\xff\xf0\x07\xfc\x01\xf8\x00\x7f\x00\x00\x00\x00\xff\xfe\x00`\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xfc\x00\x00\x00\x00\x7f\x00\x00p\x01\xc0\x7f\xff\xc0\x00\x00\x00\x7f\x00\x00\xfc\x1f\xf8\x0f\xff\xf8\x03\xe0\x00\x7f\x00\x01\xfd\xff\xfe\x01\xff\xff\x87\xf0\x00\x7f\x00\x03\xff\xff\xfe\x00?\xff\xff\xf0\x00\x7f\x00\x03\xff\xff\xf0\x00\x07\xff\xff\xf0\x00\x7f\x00\x01\xff\xff\x80\x00\x00\xff\xff\xf0\x00\x7f\x00\x00\xff\xfc\x00\x00\x00\x1f\xff\xf0\x00\x7f\x00\x00?\xc0\x00\x00\x00\x03\xff\xe0\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x7f\x80\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Snow=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\r\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0c\xc0\x00\x02\x00\x7f\x00\x00\x00\x00\x00\x00\x13 \x00\x04\x00\x7f\x00\x00\x00\x00\x00\x00?\xf0\x00"`\x7f\x00\x10\x00\x00\x00\x00\x13`\x00\x1a\xc0\x7f\x00|\x00\x00\x00\x00\x04\x80\x00\x16\x00\x7f\x020\x80\x00\x01\x00\x0e\xc0\x00\x0f\x00\x7f\x02\xde\xc0\x00\x03\x00\x02\x80\x00\x1a\xc0\x7f\x0e\xba\xe0\x003\x18\x00\x00\x00$@\x7f\x07\xbb\xc0\x00;p\x00\x00\x00\x02\x00\x7f\t\xff0\x00\x1f\xe0\x00\x00\x00\x040\x7f\x03m\x80\x0c\x07\xc0@\x00\x00\x00x\x7f\x02\xee\xc0\x0c#\x10\xc0\x00\x00\x00p\x7f\r\xff\xb0\x0c{|\xc0\x00\x00\x00\x00\x7f\x07\xff\xc0l\xff\xfc\xcc\x00\x02\x00\x00\x7f\x0e\xba\xe0\xfc\xcf\xcc\xfc\x00\x1b`\x00\x7f\x02\xfe\x80<\xd3\xac\xf0\x00\x1f\xc0\x00\x7f\x02\x10\x80\x1f\xdbo\xf0\x00\x0f\xc0\x00\x7f\x00|\x00\x7f\xcf\xef\xfc\x08\x07\x00\x80\x7f\x00T\x00\xf1\xff\xff\x1e\x08\x03\x00\xc0\x7f\x00\x10\x00\x07\xff\xff\x80\x0c\x13 \x80\x7f\x00\x00\x00\x0f?\xf3\xe0<{y\xb0\x7f\x00\x00\x00\x1c\xfc\xfd\xe0<\x7f\xd9\xe0\x7f\x00\x00\x00\x0c\xfc~ ?g\x93\xe0\x7f\x00\x00\x00\x1e<\xf0\xe0\xff\xa77\xf8\x7f\x00\x80\x00\x07\xff\xfb\xc0\xe1\xe3>8\x7f\x00\x00\x00\xe3\xff\xff\x1e\x00\xfb|\x00\x7f\x02\xe0\x00\xff\xcf\xef\xbc\x03\xff\xff\x00\x7f\x01\x80\x00?\xdbo\xf0\x06\x0f\x83\x00\x7f\x00@\x00>\xd3,\xf8\x07\x9f\xc3\x00\x7f\x00\x80\x00|\xcf\xcc\xfc\x03\xff\xff\x00\x7f\x00\x00@\xec\xff\xfc\xce\x80\xf3<\x00\x7f\x00\x00\xc0\x0c\xfb|\xc0\xf9\xe3>x\x7f\x00\x00\xe0\x0c#\x10\xc0\x7f\'7\xf8\x7f\x00\x03\xf0\x0c\x07\xc0@>o\x91\xe0\x7f\x00\x03\xf0\x00\x1f\xe0\x00<{\xd9\xf0\x7f\x00\n\xd0\x00;\xf0\x00,{q\xa0\x7f\x00\x1e\xde\x0038\x00\x0c\x03\x00\xc0\x7f\x0e\x9c\xce|\x03\x00\x00\x08\x03\x00\xc0\x7f\x07\x87\xf8|\x01\x00\x00\x08\x07\x00\x80\x7f\x05\x8f\xdc|\x00\x00\x00\x00\x0f\xc0\x00\x7f\x03\xfe\xde\xf8\x00\x00\x00\x00\x1f\xe0\x00\x7f\x009\xf3\x10\x00\x00\x00\x00\x1b`\x00\x7f\x01\x9f\xff \x00\x00\x00\x00\x00\x00\x00\x7f\x00\xa7\xf9`\x00\x00\x00\x00\x10\x00\x00\x7f\x01\xff\xff\xe0\x00\x00\x00\x00\\\x00\x00\x7f\x01\xff\xff\xf0\x00\x00\x00\x008\x00\x00\x7f\x00\xa7\xfd`\x00\x00\x00\x02T\x80\x00\x7f\x01\x9d\xff \x00\x00\x00\x0e\xfe\xe0\x00\x7f\x033\xf3\x98\x00\x00\x00\x07\x9b\xc0\x00\x7f\x05\xde\xde\xe0\x00\x00\x00\r\xffp\x00\x7f\x07\x87\xd8|\x00\x02\x00\x03\x7f\x80\x00\x7f\x0f\xaf\xfd|\x00\x00\x00\x02\xee\xc0\x00\x7f\x02\x8c\xce0\x00\x12 \x03\xff\x80\x00\x7f\x00\x1e\xce\x00\x00\t\x80\r\xffp\x00\x7f\x00\x02\xc8\x00\x00\x07\x00\x07\xbb\xc0\x00\x7f\x00\x01\xf0\x00\x00\x0b\x80\x0e\xfe\xe0\x00\x7f\x00\x03\xd0\x00\x00\x19`\x02\xd4\x80\x00\x7f\x00\x01\xe0\x00\x00\x00\x00\x008\x80\x00\x7f\x00\x00\xe0\x00\x00\x03\x00\x00\\\x00\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x10\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Target=b"P4\n89 64\n\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xfb\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xf8\x08\x1f\xe0\x00\x00\x00\x7f\x00\x00\x00\x07\xe1\x00\x01\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x10\x84 \xfc\x00\x00\x00\x7f\x00\x00\x00<\x00B\x10\x1e\x00\x00\x00\x7f\x00\x00\x00x\x84!\x08O\x00\x00\x00\x7f\x00\x00\x00\xe0B\x10\x84\x03\x80\x00\x00\x7f\x00\x00\x01\xe4!\x08B\x13\xc0\x00\x00\x7f\x00\x00\x03\x82\x10\x84!\x01\xe0\x00\x00\x7f\x00\x00\x07\xa1\x08B\x10\x84\xf0\x00\x00\x7f\x00\x00\x0e\x10\x84 \x08@x\x00\x00\x7f\x00\x00\x0e\x08B\x0c\x84!8\x00\x00\x7f\x00\x00\x1c\x84 \x08B\x10\x1c\x00\x00\x7f\x00\x008B\x10\xff\x01\x08N\x00\x00\x7f\x00\x008!\x03\xff\xe0\x84\x0e\x00\x00\x7f\x00\x00r\x10\x8f\x89\xf8B\x17\x00\x00\x7f\x00\x00q\x08\x1eU\xaa\xf8\x83\xf0\x00\x7f\x00\x01\xc8\x0b\x15MUp@\xe0\x00\x7f\x00\x01\x84'j\xaa\x95d!\xc0\x00\x7f\x00\x01\xc2\x03\x95Ujb\x01\xc0\x00\x7f\x00\x01\xc1\x0b\xaa\xaa\x92\xe1\t\xc0\x00\x7f\x00\x01\xc0\x81\xaa\xb6n\xc0\x85\xc0\x00\x7f\x00\x01\xc8C\xd5I\x91\xc8A\xc0\x00\x7f\x00\x00\xe4 \xd56m\x84!\x80\x00\x7f\x00\x00\xe2\x10\xea\xc9\x93\x82\x13\x80\x00\x7f\x00\x00\xe1\x08u6w!\x03\x80\x00\x7f\x00\x00`\x849\xc9\x8e\x10\x87\x00\x00\x7f\x00\x00pB\x1e6<\x08G\x00\x00\x7f\x00\x00t!\x0f\x89\xf8\x84'\x00\x00\x7f\x00\x008\x10\x83\xff\xe0B\x0e\x00\x00\x7f\x00\x009\x08B\xff\x84!\x0e\x00\x00\x7f\x00\x00\x1c\x84 ,\x02\x10\x9c\x00\x00\x7f\x00\x00\x0eB\x10\x98!\x088\x00\x00\x7f\x00\x00\x0e\x01\x08B\x10\x848\x00\x00\x7f\x00\x00\x07\x90\x84!\x08Bp\x00\x00\x7f\x00\x00\x03\xc0B\x10\x84 \xe0\x00\x00\x7f\x00\x00\x01\xe4!\x08B\x13\xc0\x00\x00\x7f\x00\x00\x00\xe0\x10\x84!\x03\x80\x00\x00\x7f\x00\x00\x00y\x08B\x10\x8f\x00\x00\x00\x7f\x00\x00\x00<\x84!\x08\x1e\x00\x00\x00\x7f\x00\x00\x00\x1f\x02\x10\x84|\x00\x00\x00\x7f\x00\x00\x00\x07\xc1\x00A\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xf8\x08\x0f\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xeb\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" diff --git a/mixly/boards/default_src/micropython/origin/build/lib/oled128x64.py b/mixly/boards/default_src/micropython/origin/build/lib/oled128x64.py new file mode 100644 index 00000000..d47f3673 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/oled128x64.py @@ -0,0 +1,14 @@ +""" +OLED Displays + +Micropython library for the SSD1106_I2C OLED Displays +======================================================= +@dahanzimin From the Mixly Team +""" +from ssd1106 import SSD1106_I2C + +class OLED(SSD1106_I2C): + """A single matrix.""" + def __init__(self, i2c, width=128, height=64, address=0x3c, font_address=0x700000, types=0): + super().__init__(width, height, i2c, address, l_offset=0 if types == 0 else -2) + self.font(font_address) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ollama.py b/mixly/boards/default_src/micropython/origin/build/lib/ollama.py new file mode 100644 index 00000000..5ecd4a78 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ollama.py @@ -0,0 +1,111 @@ +import urequests +import time +import json + + +class Ollama(): + def __init__(self, url="", model="", max_history_num=0): + self._heads = { + "Accept": "text/event-stream", + # "Cache-Control": "no-cache", + # "Connection": "keep-alive", + "Content-Type": "application/json" + } + self._url = url + self._chat_url = "{}/api/chat".format(self._url) + self._max_retries = 1 + self._max_history_num = max_history_num + self._timeout = 10000 + self._messages = [] + self._data = { + "stream": True, + "model": model, + "messages": self._messages + } + + def set_timeout(self, timeout): + self._timeout = timeout + + def set_max_retries(self, max_retries): + self._max_retries = max_retries + + def set_custom_url(self, url): + self._url = url + self._chat_url = "{}/api/chat".format(self._url) + + def select_model(self, model_name): + self._data["model"] = model_name + + def set_max_history_num(self, num): + self._max_history_num = num + + def empty_history(self): + self._messages = [] + + def add_history(self, role, content): + self._messages.append({ + "role": role, + "content": content + }) + + def clear_user_history(self): + if len(self._messages) < 2: + return + for i in range(1, len(self._messages)): + del self._messages[i] + + def _post(self, content_callback=None): + response = None + data = json.dumps(self._data).encode('utf-8') + for i in range(0, self._max_retries): + response = urequests.post( + self._chat_url, headers=self._heads, data=data) + if response.status_code == 200: + break + time.sleep(1) + + output = "" + + if response.status_code != 200: + output = response.text + if content_callback: + content_callback(output) + return output + + if not content_callback: + output = json.loads(response.text)["message"]["content"] + response.close() + return output + + try: + while True: + line = response.raw.readline() + if line: + line = line.decode('utf-8').strip() + data = json.loads(line) + if data["done"]: + break + content = data["message"]["content"] + content_callback(content) + output += content + else: + break + finally: + response.close() + return output + + def chat(self, message, content_callback=None): + self.add_history("user", message) + self._data["stream"] = bool(content_callback) + self._heads["Accept"] = "text/event-stream" if content_callback else "application/json" + content = self._post(content_callback) + if self._max_history_num: + self.add_history("assistant", content) + messages_len = len(self._messages) + history_num = 2 * self._max_history_num + while history_num < messages_len: + del self._messages[0] + else: + self.clear_user_history() + + return content diff --git a/mixly/boards/default_src/micropython/origin/build/lib/onenet.py b/mixly/boards/default_src/micropython/origin/build/lib/onenet.py new file mode 100644 index 00000000..109fc1cb --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/onenet.py @@ -0,0 +1,34 @@ +import ujson as json +from umqtt import MQTTClient,str_len + +def get_data_dict(d): + result = {"datastreams":[]} + for x in d: + result["datastreams"].append({"id":x,"datapoints":[{"value":d[x]}]}) + return result + +def pubData(value, state): + value = get_data_dict(value) + jdata = json.dumps(value) + jlen = str_len(jdata) + bdata = bytearray(jlen+3) + bdata[0] = 1 #publish data in type of json + bdata[1] = int(jlen / 256) # data lenght + bdata[2] = jlen % 256 # data lenght + bdata[3:jlen+4] = jdata.encode('ascii') # json data + if state: + print(value) + #print(bdata) + return bdata + +def init_MQTT_client(sid, address, cid, api, topic, callback): + client = MQTT_Client(sid, address, 6002, cid, api) + client.set_callback(callback) + client.connect() + client.subscribe(bytes(topic, 'utf-8')) + return client + +#inherit +class MQTT_Client(MQTTClient): + def publish(self, msg, is_print=False, topic='$dp', retain=False, qos=0): + super().publish('$dp',pubData(msg, is_print)) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/openai.py b/mixly/boards/default_src/micropython/origin/build/lib/openai.py new file mode 100644 index 00000000..b4808ffb --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/openai.py @@ -0,0 +1,53 @@ +import urequests +import time +import json +import ollama + + +class OpenAI(ollama.Ollama): + def __init__(self, url="", api_key="", model="", max_history_num=0, max_tokens=1024): + super().__init__(url, model, max_history_num) + self._heads["Authorization"] = "Bearer {}".format(api_key) + self._data["max_tokens"] = max_tokens + self._chat_url = "{}/chat/completions".format(self._url) + + def _post(self, content_callback=None): + response = None + data = json.dumps(self._data).encode('utf-8') + for i in range(0, self._max_retries): + response = urequests.post( + self._chat_url, headers=self._heads, data=data) + if response.status_code == 200: + break + time.sleep(1) + + output = "" + + if response.status_code != 200: + output = response.text + if content_callback: + content_callback(output) + return output + + if not content_callback: + output = json.loads(response.text)[ + "choices"][0]["message"]["content"] + response.close() + return output + + try: + while True: + line = response.raw.readline() + if line[:5] != b"data:": + continue + if line[-7:-1] == b"[DONE]": + break + line = line[6:-1] + line = line.decode('utf-8').strip() + data = json.loads(line) + content = data["choices"][0]["delta"]["content"] + content_callback(content) + output += content + finally: + response.close() + return output diff --git a/mixly/boards/default_src/micropython/origin/build/lib/pe_g1.py b/mixly/boards/default_src/micropython/origin/build/lib/pe_g1.py new file mode 100644 index 00000000..ffba026a --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/pe_g1.py @@ -0,0 +1,126 @@ +""" +Micropython library for +PE_G1 (Motor*5*2 & Servo*4) +MDB (Motor*4*2 & Servo*6) +=============================== +@dahanzimin From the Mixly Team +""" +from time import sleep_ms +from micropython import const + +_PE_GX_ADDRESS = const(0x25) +_PE_GX_ID = const(0x00) +_PE_GX_VBAT = const(0x01) +_PE_GX_MOTOR = const(0x03) + +class PE_G1: + def __init__(self, i2c_bus, addr=_PE_GX_ADDRESS): + self._i2c = i2c_bus + self._addr = addr + sleep_ms(500) + if self._rreg(_PE_GX_ID) == 0x25: + self._PE_GX_SERVO = 0x0D + self._type = 1 #PE_G1 + elif self._rreg(_PE_GX_ID) == 0x26: + self._PE_GX_SERVO = 0x0B + self._type = 2 #MDB + else: + raise AttributeError("Cannot find a PE_G1 or MDB") + self.reset() + + def _wreg(self, reg, val): + '''Write memory address''' + try: + self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little')) + except: + return 0 + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + try: + self._i2c.writeto(self._addr, reg.to_bytes(1, 'little')) + return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes <= 1 else self._i2c.readfrom(self._addr, nbytes) + except: + return 0 + + def reset(self): + """Reset all registers to default state""" + if self._type == 1: + self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(18)) + if self._type == 2: + self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(20)) + + def read_bat(self, ratio=1): + '''Read battery power''' + vbat = self._rreg(_PE_GX_VBAT) << 2 | self._rreg(_PE_GX_VBAT+1) >> 6 + if self._type == 1: + return round(vbat * ratio * 0.00968, 2) + if self._type == 2: + return round(vbat * ratio * 0.01398, 2) + + def m_pwm(self, index, duty=None): + """Motor PWM duty cycle data register""" + if self._type == 1: # Motor*5*2 + if not 0 <= index <= 9: + raise ValueError("Motor port must be a number in the range: 0~4") + if self._type == 2: # Motor*4*2 + if not 0 <= index <= 7: + raise ValueError("Motor port must be a number in the range: 0~3") + if duty is None: + return self._rreg(_PE_GX_MOTOR + index) + else: + if not 0 <= duty <= 255: + raise ValueError("Duty must be a number in the range: 0~255") + self._wreg(_PE_GX_MOTOR + index, duty) + + def s_pwm(self, index, duty=None): + """Servo PWM duty cycle data register""" + if self._type == 1: # Servo*4 + if not 0 <= index <= 3: + raise ValueError("Servo port must be a number in the range: 0~3") + if self._type == 2: # Servo*6 + if not 0 <= index <= 5: + raise ValueError("Servo port must be a number in the range: 0~5") + if duty is None: + return self._rreg(self._PE_GX_SERVO + index * 2) << 8 | self._rreg(self._PE_GX_SERVO + index * 2 + 1) + else: + if not 0 <= duty <= 4095: + raise ValueError("Duty must be a number in the range: 0~4095") + self._wreg(self._PE_GX_SERVO + index * 2,duty >> 8) + self._wreg(self._PE_GX_SERVO + index * 2 + 1,duty & 0xff) + + def motor(self, index, action="NC", speed=0): + if not 0 <= speed <= 100: + raise ValueError("Speed parameters must be a number in the range: 0~100") + if action == "N": + self.m_pwm(index * 2, 0) + self.m_pwm(index * 2 + 1, 0) + elif action == "P": + self.m_pwm(index * 2, 255) + self.m_pwm(index * 2 + 1, 255) + elif action == "CW": + self.m_pwm(index * 2, 0) + self.m_pwm(index * 2 + 1, speed * 255 // 100) + elif action == "CCW": + self.m_pwm(index * 2, speed * 255 // 100) + self.m_pwm(index * 2 + 1, 0) + elif action == "NC": + return round(self.m_pwm(index * 2) * 100 / 255), round(self.m_pwm(index * 2 + 1) * 100 / 255) + else: + raise ValueError('Invalid input, valid are "N","P","CW","CCW"') + + def servo180(self, index, angle=None): + if angle is None: + return round((self.s_pwm(index) - 102.375) * 180 / 409.5) + else: + if not 0 <= angle <= 180: + raise ValueError("Servo(180) angle must be a number in the range: 0~180") + self.s_pwm(index,round(102.375 + 409.5 / 180 * angle)) + + def servo360(self, index, speed=None): + if speed is None: + return round((self.s_pwm(index) - 102.375) * 200 / 409.5 - 100) + else: + if not -100 <= speed <= 100: + raise ValueError("Servo(360) speed must be a number in the range: -100~100") + self.s_pwm(index,round(102.375 + 409.5 / 200 * (speed + 100))) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/pm2_5.py b/mixly/boards/default_src/micropython/origin/build/lib/pm2_5.py new file mode 100644 index 00000000..d7989822 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/pm2_5.py @@ -0,0 +1,41 @@ +""" +PM2.5 + +Micropython library for the PM2.5(UART) +======================================================= +#Preliminary composition 20220908 + +dahanzimin From the Mixly Team +""" +import time + +class PM2_5: + def __init__(self, uart): + self._uart=uart + self._uart.init(baudrate=9600) + self._pm=(0,0) + self._flag=False + if not self._chip_id(): + raise AttributeError("Cannot find a PM2.5") + + def _rreg(self): + '''Read data''' + if self._uart.any(): + eec=0 + buf=self._uart.read(7) + for i in buf[1:5]: + eec+=i + if (eec & 0xff) == buf[5] and buf[0] == 0xAA and buf[6] == 0xFF: + self._pm=(buf[1] << 8 | buf[2] , buf[3] << 8 | buf[4] ) + return True + + def _chip_id(self): + for _ in range(5): + if self._rreg(): + return True + time.sleep(1) + return False + + def concentration(self): + self._rreg() + return self._pm diff --git a/mixly/boards/default_src/micropython/origin/build/lib/progres_picture.py b/mixly/boards/default_src/micropython/origin/build/lib/progres_picture.py new file mode 100644 index 00000000..5304dc14 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/progres_picture.py @@ -0,0 +1,29 @@ +#Take the picture bytes in progres_picture.py +#--dahanzimin From the Mixly Team + +Bar_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1ca\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x16\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x002w@\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\x1ea\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05\x90\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x9c\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x86w@\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x02\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xbe\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xaa\xaa\xaa\xc0\x00\x00\x00\x00\x00\x00\xff\xd5RIU\x80\x00\x00\x00\x00\x00\x00\xff\xea\xad\xb6\xab\x00\x00\x00\x00\x00\x00\x00\xff\xd5RIV\x00\x00\x00\x00\x00\x00\x00\xff\xea\xad\xb6\xac\x00\x00\x00\x00\x00\x00\x00\xff\xd5RIX\x00\x00\x00\x00\x00\x00\x00\xff\xd5m\xb6\xb0\x00\x00\x00\x00\x00\x00\x00\xff\xea\x92I`\x00\x00\x00\x00\x00\x00\x00\xff\xd5m\xb6\xc0\x00\x00\x00\x00\x00\x00\x00\xff\xca\x92I\x80\x00\x00\x00\x00\x00\x00\x00\xff\xfbm\xb7\x00\x00\x00\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\x9ca\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x04\x16\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x072\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xb2w@\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xb2\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x9e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xaa\xaa\xaa\xaa\xaa\xac\x00\x00\x00\x00\xff\xd5$\x92I$\x95X\x00\x00\x00\x00\xff\xea\xdbm\xb6\xdbj\xb0\x00\x00\x00\x00\xff\xd5$\x92I$\x95`\x00\x00\x00\x00\xff\xd6\xdbm\xb6\xdbj\xc0\x00\x00\x00\x00\xff\xe9$\x92I$\x95\x80\x00\x00\x00\x00\xff\xd6\xdbm\xb6\xdbk\x00\x00\x00\x00\x00\xff\xc9$\x92I$\x96\x00\x00\x00\x00\x00\xff\xf6\xdbm\xb6\xdbl\x00\x00\x00\x00\x00\xff\xc9$\x92I$\x98\x00\x00\x00\x00\x00\xff\xf6\xdbm\xb6\xdbp\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x9ea\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x90\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x9c\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x06w@\x00\x00\x00\x7f\x00\x00\x00\x00\x02\x02\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x06>\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd5UUUUUUUU\x80\x00\xff\xd5RI$\x92I$\x92\xab\x00\x00\xff\xea\xad\xb6\xdbm\xb6\xdbmV\x00\x00\xff\xd5RI$\x92I$\x92\xac\x00\x00\xff\xea\xad\xb6\xdbm\xb6\xdbmX\x00\x00\xff\xd5RI$\x92I$\x92\xb0\x00\x00\xff\xd5m\xb6\xdbm\xb6\xdbm`\x00\x00\xff\xea\x92I$\x92I$\x92\xc0\x00\x00\xff\xd5m\xb6\xdbm\xb6\xdbm\x80\x00\x00\xff\xca\x92I$\x92I$\x93\x00\x00\x00\xff\xfbm\xb6\xdbm\xb6\xdbn\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Bar_4=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x87\x1ca\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xc5\x96\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2w@\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2\x0b@\x00\x00\x00\x7f\x00\x00\x00\x01\xe7\x9e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd5UUUUUUUUUU\xff\xd5$\x92I$\x92I$\x92I*\xff\xea\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xd5$\x92I$\x92I$\x92I+\xff\xd6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xe9$\x92I$\x92I$\x92I+\xff\xd6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xc9$\x92I$\x92I$\x92I+\xff\xf6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xc9$\x92I$\x92I$\x92I%\xff\xf6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xdb\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x0c\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00w@\x00\x00\x02\xc0\x7f\x00\x80\x00?\xff\xf9\x00\x00\x00\x00@\x7f\x07\xe1\x7f\xff\xff\xfd\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\xff\xff\xff\xfc\x80\x00\x00\x03\xf8\x7f\x00\x00\x00?\xff\xfd\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xfb\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x88\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x02\x80\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x83\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x01\x80\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\xc0\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00`\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x010\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x1c\x80\x00\x00\x00\x00\x17\x00\x7f\x00t\x00N@\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x0f \x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x17\x80\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x03\xc0\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x05\xf0\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\xf8\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00|\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00>@\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x1f\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x0f\xd0\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x0f\xe0\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x07\xf1\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x13\xfc\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x01\xff@\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x04\xf9\x00\x00\x00\x00@\x7f\x07\xe4\x00\x00\x02}\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xfc\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x02\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x08\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00$\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x0c\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x0c\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x0c\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x0c\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x0c\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x0c\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x0c\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x0c\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x0c\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x0c\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00N\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x1e\x80\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x1e\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x1e\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x1e\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x1e\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x1e\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00?\x00\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01\x7f\x00\x00\x00\x00@\x7f\x07\xe4\x00\x00\x00\x7f\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xde\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x0b`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x10\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00 \x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x02H\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\xd0\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x03\x80\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x07\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00N\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x1c\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x008\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\xf0\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\t\xe4\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x03\xc0\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x07\xd0\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x1f\x80\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00?\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00~\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x04\xfc\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\xf8\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x03\xf2\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x0f\xe0\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00?\xc0\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01o\xd0\x00\x00\x00@\x7f\x07\xe4\x00\x00\x00O\x80\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xcf\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00a\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dial_4=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x1c\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x007\x00\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01o\xff\xf0\x00\x00@\x7f\x07\xe4\x00\x00\x00O\xff\xff\xff\xab\xf8\x7f\x0f\xf0\x00\x00\x00\xcf\xff\xff\xff\x83\xf8\x7f\x00\x00\x00\x00\x00O\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f" +Dots_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00 \x01\x02\x00\x10 \x01\x00\x00\x7f\x00\x00\x10\x02\x01\x00 \x10\x02\x00\x00\x7f\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x0f\xc0\x00\x80\x00\x7f\x00\x00@\x00\xfc\x00\x0f\xc0\x00\x00\x00\x7f\x00\x00@\x00\x84\x00\x08@\x00\x80\x00\x7f\x00\x00\x00\x02\x00\x00 \x00\x02\x00\x00\x7f\x00\x00(\x01\x02\x80\x10(\x01\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x80\x00\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dots_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x03\xf0\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x07\xf8\x00@\x80\x04\x08\x00\x00\x7f\x00\x00/\xfd\x02\x00\x10 \x01\x00\x00\x7f\x00\x00\x1f\xfe\x01\x00 \x10\x02\x00\x00\x7f\x00\x00\x1f\xfe\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00_\xfe\xfc\x00\x0f\xc0\x00\x80\x00\x7f\x00\x00\x1f\xfe\xfc\x00\x0f\xc0\x00\x00\x00\x7f\x00\x00_\xfe\x84\x00\x08@\x00\x80\x00\x7f\x00\x00\x1f\xfe\x00\x00 \x00\x02\x00\x00\x7f\x00\x00/\xfd\x02\x80\x10(\x01\x00\x00\x7f\x00\x00\x07\xf8\x00\x00\x80\x00\x08\x00\x00\x7f\x00\x00\x03\xf0\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dots_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00?\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00\x7f\x80\x04\x08\x00\x00\x7f\x00\x00 \x01\x02\xff\xd0 \x01\x00\x00\x7f\x00\x00\x10\x02\x01\xff\xe0\x10\x02\x00\x00\x7f\x00\x00@\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfd\xff\xef\xc0\x00\x80\x00\x7f\x00\x00@\x00\xfd\xff\xef\xc0\x00\x00\x00\x7f\x00\x00@\x00\x85\xff\xe8@\x00\x80\x00\x7f\x00\x00\x00\x02\x01\xff\xe0\x00\x02\x00\x00\x7f\x00\x00(\x01\x02\xff\xd0(\x01\x00\x00\x7f\x00\x00\x00\x08\x00\x7f\x80\x00\x08\x00\x00\x7f\x00\x00\x02\x10\x00?\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Dots_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x03\xf0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x07\xf8\x00\x00\x7f\x00\x00 \x01\x02\x00\x10/\xfd\x00\x00\x7f\x00\x00\x10\x02\x01\x00 \x1f\xfe\x00\x00\x7f\x00\x00@\x00\x00\x00\x00\x1f\xfe\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x0f\xdf\xfe\x80\x00\x7f\x00\x00@\x00\xfc\x00\x0f\xdf\xfe\x00\x00\x7f\x00\x00@\x00\x84\x00\x08_\xfe\x80\x00\x7f\x00\x00\x00\x02\x00\x00 \x1f\xfe\x00\x00\x7f\x00\x00(\x01\x02\x80\x10/\xfd\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x80\x07\xf8\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x03\xf0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hourglass_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf0\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06UUUP\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x02UUU0\x00\x00\x00\x7f\x00\x00\x00\x03UUU \x00\x00\x00\x7f\x00\x00\x00\x01\xaa\xaa\xaa`\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UT\xc0\x00\x00\x00\x7f\x00\x00\x00\x00j\xaa\xa9\x80\x00\x00\x00\x7f\x00\x00\x00\x005US\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xa6\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rUL\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x98\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xaa`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xd4\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00i\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc1\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x88\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x080\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0c\x00\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x08\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x08\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x08\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x00\x00`\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x08\x000\x00\x00\x00\x7f\x00\x00\x00\x02\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x06\x00\n\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00*\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00U@\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x01U@\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x02\xaa\xa8\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x05UT\x10\x00\x00\x00\x7f\x00\x00\x00\x06]\xb6\xdb\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf8\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hourglass_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf0\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x02\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x00\x00 \x00\x00\x00\x7f\x00\x00\x00\x01\x80\x00\x00`\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00`*\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x002\xaa\x83\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xa6\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rUL\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x98\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xaa`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xd4\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00i\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc9\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x08`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x000\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0c\x08\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x08\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x08\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x14\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\x00U\x00`\x00\x00\x00\x7f\x00\x00\x00\x03\x00\xaa\x800\x00\x00\x00\x7f\x00\x00\x00\x02\x05U@0\x00\x00\x00\x7f\x00\x00\x00\x06\x15UT\x10\x00\x00\x00\x7f\x00\x00\x00\x06UUU\x10\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06UUUP\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xdbm\xb6\xd0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf8\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Hourglass_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\x90\x00\x00\x00\x00\x00\x05\x80\x00\x7f\x00\x00\x9f\xfc\x00\x00\x00\x1f\xfc\x80\x00\x7f\x00\x00\x9f\xff\x80\x00\x00\x7f\xfc\x80\x00\x7f\x00\x00\x94\x01\xc0\x00\x00\xc0\x14\x80\x00\x7f\x00\x00\x9c\x00`\x00\x01\x80\x1c\x80\x00\x7f\x00\x00\x94\x000\x00\x03\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x18\x00\x06\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x0c\x00\x0c\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x06\x00\x18\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x03\x000\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x01\x80`\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x00\xc0\xc0\x00\x14\x80\x00\x7f\x00\x00\x9d\x00\x00a\x80\x00\x1c\x80\x00\x7f\x00\x00\x95@\x003\x00\x00\x14\x80\x00\x7f\x00\x00\x9dP\x00\x1e\x00\x00\x1c\x80\x00\x7f\x00\x00\x94\xb4\x00\x0c\x00\x00\x14\x80\x00\x7f\x00\x00\xbdJ@\x00\x00\x00\x1d\x80\x00\x7f\x00\x00\xf4\xb5\xa9\x00\x00\x00\x15\x80\x00\x7f\x00\x00\xfdJU\\\x00\x00\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xaa\xb6\x00\x00\x17\x80\x00\x7f\x00\x00\xfdJUc\x00\x00\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xaa\xc1\x85\x00\x17\x80\x00\x7f\x00\x00\xfdJU\x80\xca\xc0\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xab\x00e*W\x80\x00\x7f\x00\x00\xfdJV\x002\xda\x9f\x80\x00\x7f\x00\x00\xf4\xb5\xac\x00\x19%W\x80\x00\x7f\x00\x00\xfdJX\x00\x0c\xda\x9f\x80\x00\x7f\x00\x00\xf5u\xb0\x00\x06%W\x80\x00\x7f\x00\x00\xfd\n`\x00\x039_\x80\x00\x7f\x00\x00\xf5\xf8\xc0\x00\x01\x87W\x80\x00\x7f\x00\x00\xfc\x03\x80\x00\x00\xf0_\x80\x00\x7f\x00\x00\xff\xff\x00\x00\x00?\xff\x80\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x0f\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80/\x00|p\x00\x00\x7f\x00\x00\x01\xbe\x00!\x00>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!\x00\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00#\x00\x07\x80\x00\x00\x7f\x00\x00\x01\xe0\x00.\x00\x03\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(\x00\x01\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(\x00\x00\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/\x00\x00p\x00\x00\x7f\x00\x00\x07\x00\x00\x00\x00\x00x\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x00y\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x00q \x00\x00\x00\x00G\x00\x00\x7f\x00\x00q \x00\x00\x00\x00G\x00\x00\x7f\x00\x00q\xe0\x00\x00\x00\x01\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00G\x00\x00\x7f\x00\x00x \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x009\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x07\x80\x00\x1e\x00\x00x\x00\x00\x7f\x00\x00\x03\x80\x00\x10\x00\x00\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1e\x00\x03\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\x00\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\x00>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00\x00\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!U\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!*\x87\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/U\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(*Q\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(U\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/*Tp\x00\x00\x7f\x00\x00\x07\x00\x00\x00U\xa8x\x00\x00\x7f\x00\x00\x0f\x00\x00\x00RV8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05m\xa9<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\x92V\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05m\xa9\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\n\x92V\x8e\x00\x00\x7f\x00\x008\x00\x00\x05m\xa8\x8e\x00\x00\x7f\x00\x008\x00\x00\n\x92W\xcf\x00\x00\x7f\x00\x008\x00\x00\x05m\xa8\x0f\x00\x00\x7f\x00\x008\x00\x00\n\x92P\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05m\xb3\xc7\x00\x00\x7f\x00\x00q \x00\n\x92HG\x00\x00\x7f\x00\x00q \x00\x05m\xb4G\x00\x00\x7f\x00\x00q\xe0\x00\x04\x92I\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00G\x00\x00\x7f\x00\x00x \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x009\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x07\x80\x00\x1e\x00\x00x\x00\x00\x7f\x00\x00\x03\x80\x00\x10\x00\x00\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1e\x00\x03\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\x00\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\x00>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00\x00\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!UG\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/UTp\x00\x00\x7f\x00\x00\x07\x00\x00\x00UTx\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UU\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UV\x8e\x00\x00\x7f\x00\x008\x00\x00\x05UP\x8e\x00\x00\x7f\x00\x008\x00\x00\n\xaa\xaf\xcf\x00\x00\x7f\x00\x008\x00\x00\x05UP\x0f\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x00q \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00q \x00\x05UTG\x00\x00\x7f\x00\x00q\xe0\x00\n\xaa\xa9\xc7\x00\x00\x7f\x00\x00p \x00\x05UT\xc7\x00\x00\x7f\x00\x00p \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00x \x00\x05UP\xc7\x00\x00\x7f\x00\x009\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x008\x00\x00\x05UUO\x00\x00\x7f\x00\x008\x00\x00\x05UUN\x00\x00\x7f\x00\x00<\x00\x00\n\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UUN\x00\x00\x7f\x00\x00\x1c\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1e\x00\x00\x05UU\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x80\x00\x1eUTx\x00\x00\x7f\x00\x00\x03\x80\x00\x10\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x11J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!UG\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/UTp\x00\x00\x7f\x00\x00\x07\x00\x00\x00UTx\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UU\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UV\x8e\x00\x00\x7f\x00\x008\x00\x00\x05UP\x8e\x00\x00\x7f\x00\x008\x00\x00\n\xaa\xaf\xcf\x00\x00\x7f\x00\x008\x00\x00\x05UP\x0f\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x00q \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00q \x00\x05UTG\x00\x00\x7f\x00\x00q\xe0\x00\n\xaa\xa9\xc7\x00\x00\x7f\x00\x00p%UUUT\xc7\x00\x00\x7f\x00\x00p"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00x%UUUP\xc7\x00\x00\x7f\x00\x009\xe5UUUS\xc7\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x07\x00\x00\x7f\x00\x008\xd5UUUUO\x00\x00\x7f\x00\x008UUUUUN\x00\x00\x7f\x00\x00<\xaa\xaa\xaa\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1cUUUUUN\x00\x00\x7f\x00\x00\x1cUUUUU\x9c\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x1c\x00\x00\x7f\x00\x00\x0e\x15UUUU<\x00\x00\x7f\x00\x00\x0f\x15U@\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x8a\xaa\x9eUTx\x00\x00\x7f\x00\x00\x03\x8a\xaa\x90\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc2\xaa\x91J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe2\xaa\x90\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\xaa\x9eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x*\x92\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<*\x92J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x05\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x80@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Timer_4=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x81.@|p\x00\x00\x7f\x00\x00\x01\xbe\x15#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc*!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0U!UG\x80\x00\x00\x7f\x00\x00\x01\xe1U/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc1U(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc5U(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x85U/UTp\x00\x00\x7f\x00\x00\x07\x15U\x00UTx\x00\x00\x7f\x00\x00\x0f\n\xaa\x80\xaa\xaa8\x00\x00\x7f\x00\x00\x0e*\xaa\xaa\xaa\xaa<\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1cUUUUU\x1e\x00\x00\x7f\x00\x00\x1cUUUUU\x8e\x00\x00\x7f\x00\x008\x15UUUTN\x00\x00\x7f\x00\x008\xf5UUUW\xcf\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x0f\x00\x00\x7f\x00\x008\x05UUUP\x07\x00\x00\x7f\x00\x00y\xe5UUUS\xc7\x00\x00\x7f\x00\x00q"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00q%UUUTG\x00\x00\x7f\x00\x00q\xe2\xaa\xaa\xaa\xa9\xc7\x00\x00\x7f\x00\x00p%UUUT\xc7\x00\x00\x7f\x00\x00p"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00x%UUUP\xc7\x00\x00\x7f\x00\x009\xe5UUUS\xc7\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x07\x00\x00\x7f\x00\x008\xd5UUUUO\x00\x00\x7f\x00\x008UUUUUN\x00\x00\x7f\x00\x00<\xaa\xaa\xaa\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1cUUUUUN\x00\x00\x7f\x00\x00\x1cUUUUU\x9c\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x1c\x00\x00\x7f\x00\x00\x0e\x15UUUU<\x00\x00\x7f\x00\x00\x0f\x15U@\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x8a\xaa\x9eUTx\x00\x00\x7f\x00\x00\x03\x8a\xaa\x90\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc2\xaa\x91J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe2\xaa\x90\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\xaa\x9eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x*\x92\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<*\x92J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x05\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x80@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f' +Water_level_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff>?\xcf\xff\xff\xff\xff\xfd\xff\xff\xbf\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Water_level_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff>?\xcf\xff\xff\xff\xff\xfd\xff\xff\xbf\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Water_level_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff\x1e?\xcf\xff\xff\xff\xff\xfd\xff\xff?\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' +Water_level_3=b'P4\n89 64\n\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff\x1e?\xcf\xff\xff\xff\xff\xfd\xff\xff?\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe1\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xbf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8o\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0O\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xe0\x1f\xff\xff\xff\xff\x17\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\x07\xff\xff\xff\xff\xff\xfco\xff\xff\xff\xff\x07\xff\xff\xff\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ps2.py b/mixly/boards/default_src/micropython/origin/build/lib/ps2.py new file mode 100644 index 00000000..298263e6 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ps2.py @@ -0,0 +1,115 @@ +""" +PS2Controller + +MicroPython library for the PS2Controller +======================================================= + +#Perform upgrade repair 20220819 + +dahanzimin From the Mixly Team +""" + +import time +from machine import Pin +from micropython import const + +PSB_SELECT = const(0x0001) +PSB_L3 = const(0x0002) +PSB_R3 = const(0x0004) +PSB_START = const(0x0008) +PSB_PAD_UP = const(0x0010) +PSB_PAD_RIGHT = const(0x0020) +PSB_PAD_DOWN = const(0x0040) +PSB_PAD_LEFT = const(0x0080) +PSB_L2 = const(0x0100) +PSB_R2 = const(0x0200) +PSB_L1 = const(0x0400) +PSB_R1 = const(0x0800) +PSB_GREEN = const(0x1000) +PSB_RED = const(0x2000) +PSB_BLUE = const(0x4000) +PSB_PINK = const(0x8000) +PSB_TRIANGLE = const(0x1000) +PSB_CIRCLE = const(0x2000) +PSB_CROSS = const(0x4000) +PSB_SQUARE = const(0x8000) + +PSS_RX = const(0) +PSS_RY = const(1) +PSS_LX = const(2) +PSS_LY = const(3) + +class PS2Controller: + def __init__(self,clk_pin,do_pin,di_pin,cs_pin,mode=1,timeout=1000): #mode: 0 red; 1 green + self.di =Pin(di_pin,Pin.IN) + self.do =Pin(do_pin,Pin.OUT) + self.cs =Pin(cs_pin,Pin.OUT) + self.clk=Pin(clk_pin,Pin.OUT) + + self.buttons=0 + self.last_buttons=0 + self.rods=(128,128,128,128) + self.motor1=0 + self.motor2=0 + + timestamp = time.ticks_ms() + while not (self._cmds([0x01,0x42])[1] in [0x41,0x73,0x79,0xF3]): + if time.ticks_diff(time.ticks_ms(), timestamp) > timeout: + raise AttributeError("Cannot find a PS2Controller",self._cmds([0x01,0x42])[1]) + + self._cmds([0x01,0x43,0x00,0x01,0x00]) # 进入配置模式 + time.sleep_ms(10) + self._cmds([0x01,0x44,0x00,mode,0x03,0x00,0x00,0x00,0x00]) # “红绿灯”配置模式 + time.sleep_ms(10) + self._cmds([0x01,0x4D,0x00,0x00,0x01]) # 开启震动模式 + time.sleep_ms(10) + self._cmds([0x01,0x43,0x00,0x00,0x5A,0x5A,0x5A,0x5A,0x5A]) # 完成并保存配置 + time.sleep_ms(10) + + def _cmd(self,cmd): + '''Single byte command sending and receiving''' + ret = 0 + for i in range(8): + if cmd & 1 << i: + self.do.value(1) + else: + self.do.value(0) + self.clk.value(0) + time.sleep_us(10) + if self.di.value(): + ret |= 1 << i + self.clk.value(1) + self.do.value(1) + time.sleep_us(10) + return ret + + def _cmds(self,cmds): + '''Multi byte command sending and receiving''' + self.cs.value(0) + buffer=bytearray(9) + for i, cmd in enumerate(cmds): + buffer[i]=self._cmd(cmd) + self.cs.value(1) + time.sleep_ms(10) + return buffer + + def keydata(self): + """Read the value of the key""" + _buffer=self._cmds([0X01, 0X42, 0X00, self.motor1, self.motor2, 0X00, 0X00, 0X00, 0X00]) + if _buffer[2]==0x5A: + handkey=(_buffer[4]<<8)| _buffer[3] + self.buttons=-handkey-1 & 0xffff + self.rods=(_buffer[5],_buffer[6],_buffer[7],_buffer[8]) + return self.buttons,self.rods + + def vibration(self,motor1=0,motor2=0): + """Vibration settings""" + self.motor1=motor1 #motor1:小电机,只有震和不振 + self.motor2=0 if motor2<1 else motor2*0xBF//100+0X40 #motor2:大电机,范围0x40-0xff,映射0-100 + self._cmds([0X01, 0X42, 0X00, self.motor1, self.motor2, 0X00, 0X00, 0X00, 0X00]) + + def button(self,psb): + return (self.keydata()[0] & psb) > 0 + + def analog(self,pss): + return self.keydata()[1][pss] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/qmc5883l.py b/mixly/boards/default_src/micropython/origin/build/lib/qmc5883l.py new file mode 100644 index 00000000..678ee7fc --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/qmc5883l.py @@ -0,0 +1,215 @@ +""" +QMC5883L + +MicroPython library for the QMC5883L 3-Axis Magnetic Sensor +======================================================= +#Preliminary composition 20220217 + +by https://github.com/RigacciOrg/py-qmc5883l.git + +dahanzimin From the Mixly Team +""" + +import math +import time +from micropython import const + +I2CADDR_DEFAULT = const(0x0D) # Default I2C address + +REG_XOUT_LSB = const(0x00) # Output Data Registers for magnetic sensor. +REG_YOUT_LSB = const(0x02) # Output Data Registers for magnetic sensor. +REG_ZOUT_LSB = const(0x04) # Output Data Registers for magnetic sensor. +REG_STATUS_1 = const(0x06) # Status Register. +REG_TOUT_LSB = const(0x07) # Output Data Registers for temperature. + +REG_CONTROL_1 = const(0x09) # Reg to control mode of compass. +REG_CONTROL_2 = const(0x0A) # Reg to contro2 mode of compass. +REG_RST_PERIOD = const(0x0B) # SET/RESET Period Register. +REG_CHIP_ID = const(0x0D) # Chip ID register. + +# Flags for Status Register #1. +STAT_DRDY = const(0b00000001) # Data Ready. +STAT_OVL = const(0b00000010) # Overflow flag. +STAT_DOR = const(0b00000100) # Data skipped for reading. +# Flags for Status Register #2. +INT_ENB = const(0b00000001) # Interrupt Pin Enabling. +SOFT_RST = const(0b10000000) # Soft Reset. +# Flags for Control Register 1. +MODE_STBY = const(0b00000000) # Standby mode. +MODE_CONT = const(0b00000001) # Continuous read mode. +ODR_10HZ = const(0b00000000) # Output Data Rate Hz. +ODR_50HZ = const(0b00000100) +ODR_100HZ = const(0b00001000) +ODR_200HZ = const(0b00001100) +RNG_2G = const(0b00000000) # Range 2 Gauss: for magnetic-clean environments. +RNG_8G = const(0b00010000) # Range 8 Gauss: for strong magnetic fields. +OSR_512 = const(0b00000000) # Over Sample Rate 512: less noise, more power. +OSR_256 = const(0b01000000) +OSR_128 = const(0b10000000) +OSR_64 = const(0b11000000) + +class Compass: + + def __init__(self,i2c_bus,ODR=ODR_200HZ,RNG=RNG_8G,OSR=OSR_512): + self._device = i2c_bus + self._address = I2CADDR_DEFAULT + self.output_range = RNG + self._declination = 0.0 + self._calibration = [[1.0, 0.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 1.0]] + self._device.scan() + time.sleep(0.1) + if self._read_byte(REG_CHIP_ID) != 0xFF: + raise AttributeError("Cannot find a QMC5883L") + + self.mode_cont = (MODE_CONT | ODR | RNG | OSR) + self.mode_stby = (MODE_STBY | ODR_10HZ | RNG_2G | OSR_64) + self.mode_continuous() + + def __del__(self): + """Once finished using the sensor, switch to standby mode.""" + self.mode_standby() + + def _write_byte(self, reg, val): + """Write memory address""" + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _read_byte(self, reg,nbytes=1): + """Read memory address""" + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def mode_continuous(self): + """Set the device in continuous read mode.""" + self._write_byte(REG_CONTROL_2, SOFT_RST) # Soft reset. + self._write_byte(REG_CONTROL_2, INT_ENB) # Disable interrupt. + self._write_byte(REG_RST_PERIOD, 0x01) # Define SET/RESET period. + self._write_byte(REG_CONTROL_1, self.mode_cont) # Set operation mode. + + def mode_standby(self): + """Set the device in standby mode.""" + self._write_byte(REG_CONTROL_2, SOFT_RST) + self._write_byte(REG_CONTROL_2, INT_ENB) + self._write_byte(REG_RST_PERIOD, 0x01) + self._write_byte(REG_CONTROL_1, self.mode_stby) # Set operation mode. + + def _read_word_2c(self, registry): + """Calculate the 2's complement of a two bytes value.""" + data=self._read_byte(registry,2) + val = (data[1] << 8) | data[0] + if val >= 0x8000: # 32768 + return val - 0x10000 # 65536 + else: + return val + + def ready(self): + return self._read_byte(REG_STATUS_1) + + def get_data(self): + """Read data from magnetic and temperature data registers.""" + i = 0 + [x, y, z, t] = [None, None, None, 0] + while i < 20: # Timeout after about 0.20 seconds. + status = self.ready() + if status & STAT_OVL: + # Some values have reached an overflow. + if self.output_range == RNG_2G: + raise AttributeError("Consider switching to RNG_8G output range") + else: + raise AttributeError("Magnetic sensor overflow") + if status & STAT_DOR: + # Previous measure was read partially, sensor in Data Lock. + x = self._read_word_2c(REG_XOUT_LSB) + y = self._read_word_2c(REG_YOUT_LSB) + z = self._read_word_2c(REG_ZOUT_LSB) + continue + if status & STAT_DRDY: + # Data is ready to read. + x = self._read_word_2c(REG_XOUT_LSB) + y = self._read_word_2c(REG_YOUT_LSB) + z = self._read_word_2c(REG_ZOUT_LSB) + t = self._read_word_2c(REG_TOUT_LSB) + break + else: + # Waiting for DRDY. + time.sleep(0.01) + i += 1 + return [x, y, z, t/100+20] + + def get_magnet_raw(self): + """Get the 3 axis values from magnetic sensor.""" + [x, y, z, t] = self.get_data() + return [x, y, z] + + def get_magnet(self): + """Return the horizontal magnetic sensor vector with (x, y) calibration applied.""" + [x, y, z] = self.get_magnet_raw() + if x is None or y is None: + [x1, y1] = [x, y] + else: + c = self._calibration + x1 = x * c[0][0] + y * c[0][1] + c[0][2] + y1 = x * c[1][0] + y * c[1][1] + c[1][2] + return [x1, y1] + + def get_bearing_raw(self): + """Horizontal bearing (in degrees) from magnetic value X and Y.""" + [x, y, z] = self.get_magnet_raw() + if x is None or y is None: + return None + else: + b = math.degrees(math.atan2(y, x)) + if b < 0: + b += 360.0 + return b + + def get_bearing(self): + """Horizontal bearing, adjusted by calibration and declination.""" + [x, y] = self.get_magnet() + if x is None or y is None: + return None + else: + b = math.degrees(math.atan2(y, x)) + if b < 0: + b += 360.0 + b += self._declination + if b < 0.0: + b += 360.0 + elif b >= 360.0: + b -= 360.0 + return round(b,2) + + def get_temp(self): + """Raw (uncalibrated) data from temperature sensor.""" + [x, y, z, t] = self.get_data() + return t + + def set_declination(self, value): + """Set the magnetic declination, in degrees.""" + try: + d = float(value) + if d < -180.0 or d > 180.0: + raise AttributeError('Declination must be >= -180 and <= 180') + else: + self._declination = d + except: + raise AttributeError('Declination must be a float value') + + def get_declination(self): + """Return the current set value of magnetic declination.""" + return self._declination + + def set_calibration(self, value): + """Set the 3x3 matrix for horizontal (x, y) magnetic vector calibration.""" + c = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] + try: + for i in range(0, 3): + for j in range(0, 3): + c[i][j] = float(value[i][j]) + self._calibration = c + except: + logging.error(u'Calibration must be a 3x3 float matrix.') + + def get_calibration(self): + """Return the current set value of the calibration matrix.""" + return self._calibration \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/qmi8658.py b/mixly/boards/default_src/micropython/origin/build/lib/qmi8658.py new file mode 100644 index 00000000..6986d7f5 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/qmi8658.py @@ -0,0 +1,111 @@ +""" +QMI8658 + +Micropython library for the QMI8658(Accelerometer+Gyroscope) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from math import atan, sqrt, degrees +from micropython import const + +QMI8658_REG_DEVICE_ID = const(0x00) + +QMI8658_REG_Ctrl1 = const(0x02) #Serial Interface and Sensor Enable +QMI8658_REG_Ctrl2 = const(0x03) #Accelerometer Settings +QMI8658_REG_Ctrl3 = const(0x04) #Gyroscope Settings +QMI8658_REG_Ctrl5 = const(0x06) #Sensor Data Processing Settings +QMI8658_REG_Ctrl7 = const(0x08) #Sensor Data Processing Settings +QMI8658_REG_Ctrl9 = const(0x0A) #Host Commands +QMI8658_REG_StatusInt = const(0x2D) #Sensor Data Available and Lock Register Address +QMI8658_REG_DATA = const(0x33) + +Qmi8658AccRange_2g = 0 #/* +/- 2g range */ +Qmi8658AccRange_4g = 1 #/* +/- 4g range */ +Qmi8658AccRange_8g = 2 #/* +/- 8g range */ +Qmi8658AccRange_16g = 3 #/* +/- 16g range */ + +Qmi8658GyrRange_16dps = 0 #/* +-16 degrees per second. */ +Qmi8658GyrRange_32dps = 1 #/* +-32 degrees per second. */ +Qmi8658GyrRange_64dps = 2 #/* +-64 degrees per second. */ +Qmi8658GyrRange_128dps = 3 #/* +-128 degrees per second. */ +Qmi8658GyrRange_256dps = 4 #/* +-256 degrees per second. */ +Qmi8658GyrRange_512dps = 5 #/* +-512 degrees per second. */ +Qmi8658GyrRange_1024dps = 6 #/* +-1024 degrees per second. */ +Qmi8658GyrRange_2048dps = 7 #/* +-2048 degrees per second. */ + +Qmi8658Acc_Gyr_Odr_8000Hz = 0x00 #/* High resolution 8000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_4000Hz = 0x01 #/* High resolution 4000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_2000Hz = 0x02 #/* High resolution 2000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_1000Hz = 0x03 #/* High resolution 1000Hz output rate. */ +Qmi8658Acc_Gyr_Odr_500Hz = 0x04 #/* High resolution 500Hz output rate. */ +Qmi8658Acc_Gyr_Odr_250Hz = 0x05 #/* High resolution 250Hz output rate. */ +Qmi8658Acc_Gyr_Odr_125Hz = 0x06 #/* High resolution 125Hz output rate. */ +Qmi8658Acc_Gyr_Odr_62_5Hz = 0x07 #/* High resolution 62.5Hz output rate. */ +Qmi8658Acc_Gyr_Odr_31_25Hz= 0x08 #/* High resolution 31.25Hz output rate. */ + +class QMI8658: + def __init__(self, i2c_bus,addr=0x6B,AccRange=Qmi8658AccRange_8g,GyrRange=Qmi8658GyrRange_2048dps,Acc_Gyr_Odr=Qmi8658Acc_Gyr_Odr_500Hz): + self._device = i2c_bus + self._address = addr + if self._chip_id() != 0x05: + raise AttributeError("Cannot find a QMI8658") + + self._wreg(QMI8658_REG_Ctrl9,0xA2) #做selftest,提高精度 + time.sleep(0.1) + self._wreg(QMI8658_REG_Ctrl1,0x60) + self._wreg(QMI8658_REG_Ctrl7,0x03) #启动 + self._wreg(QMI8658_REG_Ctrl2,(AccRange<< 4)|Acc_Gyr_Odr) #ACC-500HZ/8G + self._wreg(QMI8658_REG_Ctrl3,(GyrRange<< 4)|Acc_Gyr_Odr) #Gyr-500HZ/2048dps + self._wreg(QMI8658_REG_Ctrl5,0x75) #Gyr-14%,ACC-5.32% + self.gyr_lsb_div= 2**(11-GyrRange) + self.acc_lsb_div= 1<<(14-AccRange) + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _chip_id(self): + return self._rreg(QMI8658_REG_DEVICE_ID) + + def status(self): + return self._rreg(QMI8658_REG_StatusInt) + + def u2s(self,n): + return n if n < (1 << 15) else n - (1 << 16) + + @property + def getdata(self): + while self.status() == 0x81: + time.sleep(0.001) + _buffer=self._rreg(QMI8658_REG_DATA,14) + tmp= float(self.u2s(_buffer[1]<<8|_buffer[0]))/256.0 + acc_x=float(self.u2s(_buffer[3]<<8|_buffer[2]))/self.acc_lsb_div + acc_y=float(self.u2s(_buffer[5]<<8|_buffer[4]))/self.acc_lsb_div + acc_z=float(self.u2s(_buffer[7]<<8|_buffer[6]))/self.acc_lsb_div + gyr_x=float(self.u2s(_buffer[9]<<8|_buffer[8]))/self.gyr_lsb_div + gyr_y=float(self.u2s(_buffer[11]<<8|_buffer[10]))/self.gyr_lsb_div + gyr_z=float(self.u2s(_buffer[13]<<8|_buffer[12]))/self.gyr_lsb_div + return (acc_x,acc_y,acc_z),(gyr_x,gyr_y,gyr_z),round(tmp,2) + + def acceleration(self): + return self.getdata[0] + + def strength(self): + return sqrt(self.getdata[0][0]**2+self.getdata[0][1]**2+self.getdata[0][2]**2) + + def gyroscope(self): + return self.getdata[1] + + def temperature(self): + return self.getdata[2] + + def eulerangles(self,upright=False): + x,y,z = self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/radio.py b/mixly/boards/default_src/micropython/origin/build/lib/radio.py new file mode 100644 index 00000000..a5ae46b6 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/radio.py @@ -0,0 +1,145 @@ +""" +Radio-ESP-NOW + +Micropython library for the Radio-ESP-NOW +======================================================= +@dahanzimin From the Mixly Team +""" +try: + from esp import espnow + version = 0 +except: + import espnow + version = 1 +from ubinascii import hexlify, unhexlify +import network + +class ESPNow(espnow.ESPNow): + def __init__(self, channel=None, txpower=20): + self._on_handle = {} + self._once_irq = True + self._nic = network.WLAN(network.STA_IF) #if version else network.WLAN(network.AP_IF) + self._nic.active(True) + if channel is not None: + self.set_channel(channel, txpower) + super().__init__() + self.active(True) + + def encrypt(self, peer, pmk, add_peer=True): + super().set_pmk((pmk + "0" *16)[:16].encode()) + if add_peer: + super().add_peer(unhexlify(peer), encrypt=True) + else: + super().del_peer(unhexlify(peer)) + + def send(self, peer='ffffffffffff', msg=''): + '''Send data after error reporting and effective processing''' + try: + _peer = unhexlify(peer) + return super().send(_peer, str(msg)) + except OSError as err: + if len(err.args) < 2: + raise err + if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT': + raise OSError("Radio(ESPNOW) is not activated, unable to transmit data") + elif err.args[1] == 'ESP_ERR_ESPNOW_IF': + self._nic.active(True) + elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND': + super().add_peer(_peer, channel=self.channel) + return super().send(_peer, str(msg)) + elif err.args[1] == 'ESP_ERR_ESPNOW_NO_MEM': + raise OSError("internal ESP-NOW buffers are full") + elif err.args[1] == 'ESP_ERR_ESPNOW_ARG': + raise OSError("invalid argument") + else: + raise err + + def recv(self): + '''Receive data''' + if self.any(): + host, msg = super().recv() + return hexlify(host).decode(),msg.decode() + else : + return None,None + + def set_channel(self, channel=1, txpower=20): + if not self._nic.isconnected(): + self._nic.config(channel=channel, txpower=txpower) + else: + print("Warning: WiFi is connected, the actual espnow channel is {}".format(self.channel)) + + def _cb_handle0(self, event_code, data): + '''Callback processing conversion''' + if self._on_handle: + if isinstance(self._on_handle, list): + for func in self._on_handle: + cmd = func.__name__.rfind('__') + if cmd != -1: + cmd=func.__name__[cmd+2:] + if cmd == str(data[1].decode()): + func(hexlify(data[0]).decode(), data[1].decode()) + else: + func(hexlify(data[0]).decode(), data[1].decode()) + elif isinstance(self._on_handle, dict): + mac = hexlify(data[0]).decode() + decoded_msg = str(data[1].decode()) + if '__all__' in self._on_handle: + self._on_handle['__all__'](mac, decoded_msg) + if decoded_msg in self._on_handle: + self._on_handle[decoded_msg](mac, decoded_msg) + else: + self._on_handle(hexlify(data[0]).decode(), data[1].decode()) + + def _cb_handle1(self, ee): + '''Callback processing conversion''' + host, msg = super().recv() + if self._on_handle: + if isinstance(self._on_handle, list): + for func in self._on_handle: + cmd = func.__name__.rfind('__') + if cmd != -1: + cmd=func.__name__[cmd+2:] + if cmd == str(msg.decode()): + func(hexlify(host).decode(), msg.decode()) + else: + func(hexlify(host).decode(), msg.decode()) + elif isinstance(self._on_handle, dict): + mac = hexlify(host).decode() + decoded_msg = str(msg.decode()) + if '__all__' in self._on_handle: + self._on_handle['__all__'](mac, decoded_msg) + if decoded_msg in self._on_handle: + self._on_handle[decoded_msg](mac, decoded_msg) + else: + self._on_handle(hexlify(host).decode(), msg.decode()) + + def recv_cb(self, *args): + '''Receive callback (single dictionary or lists)''' + if len(args) >= 2: + self._on_handle.update({args[0]: args[1]}) + else: + self._on_handle = args[0] + + if self._once_irq: + self._once_irq = False + if version == 0: + self.irq(self._cb_handle0) + else: + self.irq(self._cb_handle1) + + def info(self): + '''Get the paired Mac and rssi''' + _info=[] + for i in self.peers_table: + _info.append((hexlify(i).decode(), self.peers_table[i][0])) + return _info + + @property + def mac(self): + '''Get mac address''' + return hexlify(self._nic.config('mac')).decode() + + @property + def channel(self): + '''Get channel address''' + return self._nic.config('channel') diff --git a/mixly/boards/default_src/micropython/origin/build/lib/rc522.py b/mixly/boards/default_src/micropython/origin/build/lib/rc522.py new file mode 100644 index 00000000..5ecbfb08 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/rc522.py @@ -0,0 +1,279 @@ +""" +RC522 + +Micropython library for the RC522 RFID (I2C&SPI) +======================================================= +#Preliminary composition 20231204 + +dahanzimin From the Mixly Team +""" +import machine +from micropython import const + +RC_OK = True +RC_NOTAGERR = None +RC_ERR = False +RC_REQIDL = const(0x26) +RC_REQALL = const(0x52) +RC_AUTHENT1A = const(0x60) +RC_AUTHENT1B = const(0x61) +RC_Version = const(0x37) + +class RC522: + def __init__(self, drive_bus,cs_pin=None,addr=0x28): + self._device= drive_bus + if type(drive_bus) in [machine.I2C,machine.SoftI2C]: + self._type=True + self._address = addr + elif type(drive_bus) in [machine.SPI,machine.SoftSPI]: + self._type=False + self._cs = machine.Pin(cs_pin, machine.Pin.OUT) + else: + raise ValueError("RC522 only supports I2C and SPI") + + self.init() + self.add_list=[1,2,4,5,6,8,9,10,12,13,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,56,57,58,60,61,62] + + def _wreg(self, reg, val): + '''Write memory address''' + if self._type: + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + else: + self._cs.value(0) + self._device.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))) + self._device.write(b'%c' % int(0xff & val)) + self._cs.value(1) + + def _rreg(self, reg): + '''Read memory address''' + if self._type: + return self._device.readfrom_mem(self._address, reg, 1)[0] + else: + self._cs.value(0) + self._device.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80))) + val = self._device.read(1) + self._cs.value(1) + return val[0] + + def _sflags(self, reg, mask): + self._wreg(reg, self._rreg(reg) | mask) + + def _cflags(self, reg, mask): + self._wreg(reg, self._rreg(reg) & (~mask)) + + def _tocard(self, cmd, send): + recv = [] + bits = 0 + irq_en = 0 + wait_irq =0 + n = 0 + stat = RC_ERR + if cmd == 0x0E: + irq_en = 0x12 + wait_irq = 0x10 + elif cmd == 0x0C: + irq_en = 0x77 + wait_irq = 0x30 + self._wreg(0x02, irq_en) + self._cflags(0x04, 0x80) + self._sflags(0x0A, 0x80) + self._wreg(0x01, 0x00) + for c in send: + self._wreg(0x09, c) + self._wreg(0x01, cmd) + + if cmd == 0x0C: + self._sflags(0x0D, 0x80) + + i = 100 + while True: + n = self._rreg(0x04) + i -= 1 + if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)): + break + + self._cflags(0x0D, 0x80) + if i: + if (self._rreg(0x06) & 0x1B) == 0x00: + stat = RC_OK + + if n & irq_en & 0x01: + stat = RC_NOTAGERR + elif cmd == 0x0C: + n = self._rreg(0x0A) + lbits = self._rreg(0x0C) & 0x07 + if lbits != 0: + bits = (n - 1) * 8 + lbits + else: + bits = n * 8 + if n == 0: + n = 1 + elif n > 16: + n = 16 + for _ in range(n): + recv.append(self._rreg(0x09)) + else: + stat = RC_ERR + return stat, recv, bits + + def _crc(self, data): + self._cflags(0x05, 0x04) + self._sflags(0x0A, 0x80) + for c in data: + self._wreg(0x09, c) + self._wreg(0x01, 0x03) + i = 0xFF + while True: + n = self._rreg(0x05) + i -= 1 + if not ((i != 0) and not (n & 0x04)): + break + return [self._rreg(0x22), self._rreg(0x21)] + + def init(self): + self.reset() + self._wreg(0x2A, 0x8D) + self._wreg(0x2B, 0x3E) + self._wreg(0x2D, 30) + self._wreg(0x2C, 0) + self._wreg(0x15, 0x40) + self._wreg(0x11, 0x3D) + self._wreg(0x26, 0x68) + #A32NQ32C3 Additional Register Configuration + if self._rreg(RC_Version) == 0x82: + self._wreg(0x12, 0x0) + self._wreg(0x13, 0x0) + self._wreg(0x14, 0x84) + self._wreg(0x18, 0x33) + self._wreg(0x0c, 0x10) + self.antenna_on() + + def reset(self): + self._wreg(0x01, 0x0F) + + def antenna_on(self, on=True): + if on and ~(self._rreg(0x14) & 0x03): + self._sflags(0x14, 0x03) + else: + self._cflags(0x14, 0x03) + + def request(self, mode): + self._wreg(0x0D, 0x07) + stat, recv, bits = self._tocard(0x0C, [mode]) + if (stat != RC_OK) | (bits != 0x10): + stat = RC_ERR + return stat, bits + + def anticoll(self): + ser_chk = 0 + ser = [0x93, 0x20] + self._wreg(0x0D, 0x00) + (stat, recv, bits) = self._tocard(0x0C, ser) + + if stat == RC_OK: + if len(recv) == 5: + for i in range(4): + ser_chk = ser_chk ^ recv[i] + if ser_chk != recv[4]: + stat = RC_ERR + else: + stat = RC_ERR + return stat, recv + + def select_tag(self, ser): + buf = [0x93, 0x70] + ser[:5] + buf += self._crc(buf) + (stat, recv, bits) = self._tocard(0x0C, buf) + return RC_OK if (stat == RC_OK) and (bits == 0x18) else RC_ERR + + def auth(self, mode, addr, sect, ser): + return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0] + + def stop_crypto1(self): + self._cflags(0x08, 0x08) + + def read(self, addr): + data = [0x30, addr] + data += self._crc(data) + (stat, recv, _) = self._tocard(0x0C, data) + return recv if stat == RC_OK else None + + def write(self, addr, data): + buf = [0xA0, addr] + buf += self._crc(buf) + (stat, recv, bits) = self._tocard(0x0C, buf) + + if not (stat == RC_OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): + stat = RC_ERR + else: + buf = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + for i in range(len(data)): + buf[i]=data[i] + buf += self._crc(buf) + (stat, recv, bits) = self._tocard(0x0C, buf) + if not (stat == RC_OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): + stat = RC_ERR + return stat + + def read_card(self,add,x='ALL'):#0:all,i:id,2:content + if add>=47: + raise AttributeError("Out of address range") + stat, tag_type = self.request(RC_REQALL) + if stat !=RC_OK: + stat, tag_type = self.request(RC_REQALL) + if stat == RC_OK: + (stat, raw_uid) = self.anticoll() + if stat == RC_OK: + if self.select_tag(raw_uid) == RC_OK: + key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] + if self.auth(RC_AUTHENT1A, self.add_list[add], key, raw_uid) == RC_OK: + card = self.read(self.add_list[add]) + try: + card = bytes(card).decode().replace("\x00", '') if card else None + except: + card = bytes(card) if card else None + self.stop_crypto1() + if x == "ALL": + return int('{}{}{}{}'.format(raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])), card + elif x == "id": + return int('{}{}{}{}'.format(raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])) + elif x == "content": + return card + + def write_card(self, data,add): + if add>=47: + raise AttributeError("Out of address range") + stat, tag_type = self.request(RC_REQALL) + if stat !=RC_OK: + stat, tag_type = self.request(RC_REQALL) + if stat == RC_OK: + (stat, raw_uid) = self.anticoll() + if stat == RC_OK: + if self.select_tag(raw_uid) == RC_OK: + key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] + if self.auth(RC_AUTHENT1A, self.add_list[add], key, raw_uid) == RC_OK: + try: + data =list(data.encode()) + except: + data =list(data) + if len(data)>16: + raise AttributeError("Input must be less than 16 bytes") + stat = self.write(self.add_list[add], data) + self.stop_crypto1() + if stat == RC_OK: + print('Data written to card') + return RC_OK + else: + print('Failed to write data to card') + return RC_ERR + else: + print('Authentication error') + return RC_ERR + else: + print('Failed to select tag') + return RC_ERR + else: + return RC_ERR + + def scan_card(self,stat=RC_REQIDL): + return self.request(stat)[0] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/rfm98.py b/mixly/boards/default_src/micropython/origin/build/lib/rfm98.py new file mode 100644 index 00000000..194b9819 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/rfm98.py @@ -0,0 +1,239 @@ +""" +RFM98 + +Micropython library for the RFM98 LoRa +======================================================= +#Preliminary composition 20220406 +#Rebuild and optimize execution 20220412 +#Repair receive mode 20220428 + +dahanzimin From the Mixly Team +""" +import gc +import time +from machine import Pin +from micropython import const + +_REG_FIFO = const(0x00) +_REG_OP_MODE = const(0x01) +_REG_FRF_MSB = const(0x06) +_REG_FRF_MID = const(0x07) +_REG_FRF_LSB = const(0x08) +_REG_PA_CONFIG = const(0x09) +_REG_LNA = const(0x0C) +_REG_FIFO_ADDR_PTR = const(0x0D) +_REG_FIFO_TX_BASE_ADDR = const(0x0E) +_REG_FIFO_RX_BASE_ADDR = const(0x0F) +_REG_FIFO_RX_CURRENT_ADDR = const(0x10) +_REG_IRQ_FLAGS = const(0x12) +_REG_RX_NB_BYTES = const(0x13) +_REG_PKT_SNR_VALUE = const(0x19) +_REG_PKT_RSSI_VALUE = const(0x1A) +_REG_MODEM_CONFIG1 = const(0x1D) +_REG_MODEM_CONFIG2 = const(0x1E) +_REG_PREAMBLE_MSB = const(0x20) +_REG_PREAMBLE_LSB = const(0x21) +_REG_PAYLOAD_LENGTH = const(0x22) +_REG_MODEM_CONFIG3 = const(0x26) +_REG_DIO_MAPPING1 = const(0x40) +_REG_DIO_MAPPING2 = const(0x41) +_REG_VERSION = const(0x42) +_REG_PA_DAC = const(0x4D) +_DETECTION_OPTIMIZE = const(0x31) +_DETECTION_THRESHOLD = const(0x37) + +_MODE_LONG_RANGE_MODE = const(0x88) +_MODE_SLEEP = const(0x00) +_MODE_STDBY = const(0x01) +_MODE_TX = const(0x03) +_MODE_RX = const(0x05) + +class RFM98: + def __init__(self,spi,cs_pin,frequency_mhz=433.0,signal_bandwidth=125E3,coding_rate=5,spreading_factor=7,**kw): + self._spi = spi + self._pin_ss = Pin(cs_pin, Pin.OUT) + self._frequency_mhz=frequency_mhz + self._signal_bandwidth=signal_bandwidth + self._coding_rate=coding_rate + self._spreading_factor=spreading_factor + self._kw=kw + self.init() + + def init(self): + for i in range(6): + if self._read_u8(_REG_VERSION) == 18: # No device type check! + break + if i >=5: + raise AttributeError("Cannot find a RFM9x") + time.sleep(1) + + self.sleep() + time.sleep(0.01) + if self._read_u8(_REG_OP_MODE) != (_MODE_LONG_RANGE_MODE | _MODE_SLEEP): + raise RuntimeError("Failed to configure radio for LoRa mode, check wiring!") + self._write_u8(_REG_FIFO_TX_BASE_ADDR, 0x00) # Setup entire 256 byte FIFO + self._write_u8(_REG_FIFO_RX_BASE_ADDR, 0x00) + + self.idle() + self.coding_rate(self._coding_rate) # CR: 5...8 + self.frequency_mhz(self._frequency_mhz) # Set frequency_mhz 433±10.00 + self.signal_bandwidth(self._signal_bandwidth) # BW: 7.8...500 kHz + self.spreading_factor(self._spreading_factor) # SF: 6..12 + self.enable_crc(self._kw.get('enable_crc', True)) # Set enable_crc + self.preamble_length(self._kw.get('preamble_length', 6)) + self.tx_power(self._kw.get('tx_power', 16),self._kw.get('high_power', True)) + + self._write_u8(_REG_MODEM_CONFIG3, 0x04) #set AGC - True + if 1000 /(self._signal_bandwidth / 2**self._spreading_factor) > 16: + self._write_u8(_REG_MODEM_CONFIG3, self._read_u8(_REG_MODEM_CONFIG3) | 0x08) + + def transfer(self, address, value = 0x00): + response = bytearray(1) + self._pin_ss.value(0) + self._spi.write(bytes([address])) + self._spi.write_readinto(bytes([value]), response) + self._pin_ss.value(1) + return response + + def _read_u8(self, address): + response = self.transfer(address & 0x7f) + return int.from_bytes(response, 'big') + + def _write_u8(self, address, value): + self.transfer(address | 0x80, value) + + def idle(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_STDBY) + + def sleep(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_SLEEP) + + def listen(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_RX) + self._write_u8(_REG_DIO_MAPPING1, 0x00) + self._write_u8(_REG_DIO_MAPPING2, 0x40) + + def transmit(self): + self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_TX) + self._write_u8(_REG_DIO_MAPPING1, 0x01) + self._write_u8(_REG_DIO_MAPPING2, 0x00) + + def preamble_length(self, val): + self._write_u8(_REG_PREAMBLE_MSB, (val >> 8) & 0xFF) + self._write_u8(_REG_PREAMBLE_LSB, val & 0xFF) + + def frequency_mhz(self, val): + if val < 410 or val > 525: + raise RuntimeError("frequency_mhz must be between 410 and 525") + frf = int((val * 1000000.0) /(32000000.0 / 524288)) & 0xFFFFFF + self._write_u8(_REG_FRF_MSB, frf >> 16) + self._write_u8(_REG_FRF_MID, (frf >> 8) & 0xFF) + self._write_u8(_REG_FRF_LSB, frf & 0xFF) + + def tx_power(self, val,high_power=True): + if high_power: + assert 5 <= val <= 23 + if val > 20: + self._write_u8(_REG_PA_DAC, 0x07) + val -= 3 + else: + self._write_u8(_REG_PA_DAC, 0x04) + self._write_u8(_REG_PA_CONFIG, 0x80 | (val - 5)) + else: + assert -1 <= val <= 14 + self._write_u8(_REG_PA_CONFIG, 0x70 | (val +1)) + + def packet_rssi(self): #last RSSI reading + return self._read_u8(_REG_PKT_RSSI_VALUE)-157 + + def packet_snr(self): #last SNR reading + snr_byte = self._read_u8(_REG_PKT_SNR_VALUE) + return snr_byte/4 if snr_byte<=127 else (snr_byte -256 )/4 + + def signal_bandwidth(self, val): + bw_bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000) + for bw_id, cutoff in enumerate(bw_bins): + if val <= cutoff: + break + else: + bw_id = 9 + self._write_u8(_REG_MODEM_CONFIG1,(self._read_u8(_REG_MODEM_CONFIG1) & 0x0F) | (bw_id << 4)) + if val >= 500000: + self._write_u8(_DETECTION_OPTIMIZE,(self._read_u8(_DETECTION_OPTIMIZE) | 0x80)) + self._write_u8(0x36, 0x02) + self._write_u8(0x3A, 0x7F) + else: + self._write_u8(_DETECTION_OPTIMIZE,(self._read_u8(_DETECTION_OPTIMIZE) & 0x7F)) + self._write_u8(0x36, 0x03) + if val == 7800: + self._write_u8(0x2F, 0x48) + elif val >= 62500: + self._write_u8(0x2F, 0x40) + else: + self._write_u8(0x2F, 0x44) + self._write_u8(0x30, 0) + + def coding_rate(self, val): + denominator = min(max(val, 5), 8) + cr_id = denominator - 4 + self._write_u8(_REG_MODEM_CONFIG1,(self._read_u8(_REG_MODEM_CONFIG1) & 0xF1) | (cr_id << 1)) + + def spreading_factor(self, val): + val = min(max(val, 6), 12) + self._write_u8(_DETECTION_OPTIMIZE,self._read_u8(_DETECTION_OPTIMIZE)|0x05 if val == 6 else self._read_u8(_DETECTION_OPTIMIZE)|0x03) + self._write_u8(_DETECTION_THRESHOLD, 0x0C if val == 6 else 0x0A) + self._write_u8(_REG_MODEM_CONFIG2,((self._read_u8(_REG_MODEM_CONFIG2) & 0x0F)| ((val << 4) & 0xF0))) + + def enable_crc(self, val): + if val: + self._write_u8(_REG_MODEM_CONFIG2,self._read_u8(_REG_MODEM_CONFIG2) | 0x04) + else: + self._write_u8(_REG_MODEM_CONFIG2,self._read_u8(_REG_MODEM_CONFIG2) & 0xFB) + + def irq_done(self): #irq status + return self._read_u8(_REG_IRQ_FLAGS) + + def send(self,msg,timeout=2): + self.idle() # Stop receiving to clear FIFO and keep it clear. + self._write_u8(_REG_FIFO_ADDR_PTR, 0x00) # FIFO starts at 0. + if isinstance(msg, str): + msg = msg.encode() + size = min(len(msg), 255) + for i in range(size): # write data + self._write_u8(_REG_FIFO, msg[i]) # Write payload. + self._write_u8(_REG_PAYLOAD_LENGTH, size) # Write payload and header length. + self.transmit() # Turn on transmit mode to send out the packet. + + timed_out = False + start = time.ticks_ms() + while not timed_out and not((self._read_u8(_REG_IRQ_FLAGS) & 0x8) >> 3): + if time.ticks_diff(time.ticks_ms(), start) >= timeout * 1000: + timed_out = True + + self.idle() # Enter idle mode to stop receiving other packets. + gc.collect() + self._write_u8(_REG_IRQ_FLAGS, 0xFF) # Clear interrupt. + return not timed_out + + def recv(self): + if self._read_u8(_REG_OP_MODE) != (_MODE_LONG_RANGE_MODE | _MODE_RX): + self.listen() # Enter receive mode + + flags=self.irq_done() + if flags & 0x40: + self.idle() # Enter idle mode to stop receiving other packets. + fifo_length = self._read_u8(_REG_RX_NB_BYTES) # Read the length of the FIFO. + if fifo_length > 0: # Read the data from the FIFO. + self._write_u8(_REG_FIFO_ADDR_PTR, self._read_u8(_REG_FIFO_RX_CURRENT_ADDR)) + packet = bytearray() + for i in range(fifo_length): + packet.append(self._read_u8(_REG_FIFO)) # Read the packet. + self._write_u8(_REG_IRQ_FLAGS, 0xFF) # Clear interrupt. + gc.collect() + try : + return bytes(packet).decode() + except: + return bytes(packet) + elif flags== 0x15: + print("Timeout not handled , overflow error,will restart!") + self.init() \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/rtctime.py b/mixly/boards/default_src/micropython/origin/build/lib/rtctime.py new file mode 100644 index 00000000..733901a2 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/rtctime.py @@ -0,0 +1,69 @@ +"""RTC Time""" +import gc +from time import * +from machine import RTC +import usocket as socket +import ustruct as struct + +# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 +NTP_DELTA = 3155673600 +_weekdayname = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun") +_monthname = (None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",) + +def ntptime(host="pool.ntp.org", utc=28800): + NTP_QUERY = bytearray(48) + NTP_QUERY[0] = 0x1B + addr = socket.getaddrinfo(host, 123)[0][-1] + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.settimeout(1) + res = s.sendto(NTP_QUERY, addr) + msg = s.recv(48) + finally: + del addr + s.close() + gc.collect() + val = struct.unpack("!I", msg[40:44])[0] + return gmtime(val - NTP_DELTA + utc) + +# There's currently no timezone support in MicroPython, and the RTC is set in UTC time. +def settime(times): + if isinstance(times, str): + try: + times = eval(times) + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0)) + else: + raise ValueError("Settime needs a type of length 6~8") + +def strtime(times=None): + if times is None: + times = localtime() + if isinstance(times, str): + try: + times = eval(times) + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format(*times) + else: + raise ValueError("Settime needs a type of length 6~8") + +def rfc1123_time(times=None, utc=28800): + if times is None: + times = localtime() + if isinstance(times, str): + try: + times = eval(times) + except: + raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values") + if type(times) in (tuple, list): + if 6 <= len(times) <= 8: + times = localtime(mktime(times) - utc) + return '{0}, {1:02d} {2} {3:04d} {4:02d}:{5:02d}:{6:02d} GMT'.format(_weekdayname[times[6]], times[2], _monthname[times[1]], times[0], times[3], times[4], times[5]) + else: + raise ValueError("Settime needs a type of length 6~8") diff --git a/mixly/boards/default_src/micropython/origin/build/lib/sc7a20.py b/mixly/boards/default_src/micropython/origin/build/lib/sc7a20.py new file mode 100644 index 00000000..f73c6193 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/sc7a20.py @@ -0,0 +1,72 @@ +""" +SC7A20 + +Micropython library for the SC7A20 Accelerometer +================================================= +#Preliminary composition 20240312 + +@dahanzimin From the Mixly Team +""" +import time +from math import atan,sqrt,degrees +from micropython import const + +SC7A20_ADDRESS = const(0x19) +SC7A20_REG_ID = const(0x0F) +SC7A20_REG_CTRL1 = const(0x20) +SC7A20_REG_CTRL2 = const(0x21) +SC7A20_REG_CTRL3 = const(0x22) +SC7A20_REG_CTRL4 = const(0x23) +SC7A20_REG_DATA = const(0x28) + + #2g 4g 8g 16g +_Range_X = (1024,512,256,128) + +class SC7A20: + + def __init__(self, i2c_bus, set_range=2, front=False): + self._device = i2c_bus + self._address = SC7A20_ADDRESS + self._range = set_range #default 8g range + self._front = front + + if self._rreg(SC7A20_REG_ID) != 0x11: + raise AttributeError("Cannot find a SC7A20") + self._wreg(SC7A20_REG_CTRL1, 0X77) #400HZ,xyz使能 + self._wreg(SC7A20_REG_CTRL2, 0X00) #禁止高通滤波模式 + self._wreg(SC7A20_REG_CTRL3, 0X00) #禁止中断 + self._wreg(SC7A20_REG_CTRL4, 0X00 | set_range << 4) #连续更新,设置量程 + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, 1)[0] + + def u2s(self, n): + return n if n < (1 << 7) else n - (1 << 8) + + @property + def getdata(self): + x_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 1)) << 8 | self._rreg(SC7A20_REG_DATA + 0)) >> 4) / _Range_X[self._range] + y_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 3)) << 8 | self._rreg(SC7A20_REG_DATA + 2)) >> 4) / _Range_X[self._range] + z_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 5)) << 8 | self._rreg(SC7A20_REG_DATA + 4)) >> 4) / _Range_X[self._range] + return (-x_acc, y_acc, z_acc, None) if self._front else (x_acc, y_acc, z_acc, None) + + def acceleration(self): + return self.getdata[0:3] + + def strength(self): + from math import sqrt + return sqrt(self.getdata[0]**2+self.getdata[1]**2+self.getdata[2]**2) + + def temperature(self): + return self.getdata[3] + + def eulerangles(self,upright=False): + x, y, z = self.acceleration() + pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2))) + roll = degrees(atan(x / sqrt(y ** 2 + z ** 2))) + return round(pitch,2),round(roll,2) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/sdcard.py b/mixly/boards/default_src/micropython/origin/build/lib/sdcard.py new file mode 100644 index 00000000..54425efb --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/sdcard.py @@ -0,0 +1,231 @@ +""" +MicroPython driver for SD cards using SPI bus. +""" +import time +from machine import Pin +from micropython import const + +_CMD_TIMEOUT = const(100) +_R1_IDLE_STATE = const(1 << 0) +_R1_ILLEGAL_COMMAND = const(1 << 2) +_TOKEN_CMD25 = const(0xFC) +_TOKEN_STOP_TRAN = const(0xFD) +_TOKEN_DATA = const(0xFE) + +class SDCard: + def __init__(self, spi, cs_pin=None, baudrate=50000000): + self.spi = spi + self.cs = Pin(cs_pin, Pin.OUT, value=1) if cs_pin else None + self.cmdbuf = bytearray(6) + self.dummybuf = bytearray(512) + self.tokenbuf = bytearray(1) + for i in range(512): + self.dummybuf[i] = 0xFF + self.dummybuf_memoryview = memoryview(self.dummybuf) + # initialise the card + self.init_card(baudrate) + + def init_spi(self, baudrate): + self.spi.init(baudrate=baudrate, phase=0, polarity=0) + + def init_card(self, baudrate): + # init SPI bus; use low data rate for initialisation + self.init_spi(100000) + # clock card at least 100 cycles with cs high + for i in range(16): + self.spi.write(b"\xff") + # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts) + for _ in range(5): + if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE: + break + else: + raise OSError("no SD card") + # CMD8: determine card version + r = self.cmd(8, 0x01AA, 0x87, 4) + if r == _R1_IDLE_STATE: + self.init_card_v2() + elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND): + self.init_card_v1() + else: + raise OSError("couldn't determine SD card version") + # CMD9: response R2 (R1 byte + 16-byte block read) + if self.cmd(9, 0, 0, 0, False) != 0: + raise OSError("no response from SD card") + csd = bytearray(16) + self.readinto(csd) + if csd[0] & 0xC0 == 0x40: # CSD version 2.0 + self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024 + elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB) + c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6 + c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7 + read_bl_len = csd[5] & 0b1111 + capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len) + self.sectors = capacity // 512 + else: + raise OSError("SD card CSD format not supported") + # CMD16: set block length to 512 bytes + if self.cmd(16, 512, 0) != 0: + raise OSError("can't set 512 block size") + # set to high data rate now that it's initialised + self.init_spi(baudrate) + + def init_card_v1(self): + for i in range(_CMD_TIMEOUT): + time.sleep_ms(50) + self.cmd(55, 0, 0) + if self.cmd(41, 0, 0) == 0: + # SDSC card, uses byte addressing in read/write/erase commands + self.cdv = 512 + # print("[SDCard] v1 card") + return + raise OSError("timeout waiting for v1 card") + + def init_card_v2(self): + for i in range(_CMD_TIMEOUT): + time.sleep_ms(50) + self.cmd(58, 0, 0, 4) + self.cmd(55, 0, 0) + if self.cmd(41, 0x40000000, 0) == 0: + self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte + ocr = self.tokenbuf[0] # get first byte of response, which is OCR + if not ocr & 0x40: + # SDSC card, uses byte addressing in read/write/erase commands + self.cdv = 512 + else: + # SDHC/SDXC card, uses block addressing in read/write/erase commands + self.cdv = 1 + # print("[SDCard] v2 card") + return + raise OSError("timeout waiting for v2 card") + + def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False): + if self.cs: self.cs(0) + + # create and send the command + buf = self.cmdbuf + buf[0] = 0x40 | cmd + buf[1] = arg >> 24 + buf[2] = arg >> 16 + buf[3] = arg >> 8 + buf[4] = arg + buf[5] = crc + self.spi.write(buf) + + if skip1: + self.spi.readinto(self.tokenbuf, 0xFF) + # wait for the response (response[7] == 0) + for i in range(_CMD_TIMEOUT): + self.spi.readinto(self.tokenbuf, 0xFF) + response = self.tokenbuf[0] + if not (response & 0x80): + if final < 0: + self.spi.readinto(self.tokenbuf, 0xFF) + final = -1 - final + for j in range(final): + self.spi.write(b"\xff") + if release: + if self.cs: self.cs(1) + self.spi.write(b"\xff") + return response + if self.cs: self.cs(1) + self.spi.write(b"\xff") + return -1 + + def readinto(self, buf): + if self.cs: self.cs(0) + for i in range(_CMD_TIMEOUT): + self.spi.readinto(self.tokenbuf, 0xFF) + if self.tokenbuf[0] == _TOKEN_DATA: + break + time.sleep_ms(1) + else: + if self.cs: self.cs(1) + raise OSError("timeout waiting for response") + mv = self.dummybuf_memoryview + if len(buf) != len(mv): + mv = mv[: len(buf)] + self.spi.write_readinto(mv, buf) + self.spi.write(b"\xff") + self.spi.write(b"\xff") + if self.cs: self.cs(1) + self.spi.write(b"\xff") + + def write(self, token, buf): + if self.cs: self.cs(0) + self.spi.read(1, token) + self.spi.write(buf) + self.spi.write(b"\xff") + self.spi.write(b"\xff") + if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05: + if self.cs: self.cs(1) + self.spi.write(b"\xff") + return + while self.spi.read(1, 0xFF)[0] == 0: + pass + if self.cs: self.cs(1) + self.spi.write(b"\xff") + + def write_token(self, token): + if self.cs: self.cs(0) + self.spi.read(1, token) + self.spi.write(b"\xff") + while self.spi.read(1, 0xFF)[0] == 0x00: + pass + if self.cs: self.cs(1) + self.spi.write(b"\xff") + + def readblocks(self, block_num, buf): + # workaround for shared bus, required for (at least) some Kingston + self.spi.write(b"\xff") + + nblocks = len(buf) // 512 + assert nblocks and not len(buf) % 512, "Buffer length is invalid" + if nblocks == 1: + # CMD17: set read address for single block + if self.cmd(17, block_num * self.cdv, 0, release=False) != 0: + # release the card + if self.cs: self.cs(1) + raise OSError(5) # EIO + # receive the data and release card + self.readinto(buf) + else: + # CMD18: set read address for multiple blocks + if self.cmd(18, block_num * self.cdv, 0, release=False) != 0: + if self.cs: self.cs(1) + raise OSError(5) # EIO + offset = 0 + mv = memoryview(buf) + while nblocks: + self.readinto(mv[offset : offset + 512]) + offset += 512 + nblocks -= 1 + if self.cmd(12, 0, 0xFF, skip1=True): + raise OSError(5) # EIO + + def writeblocks(self, block_num, buf): + # workaround for shared bus, required for (at least) some Kingston + self.spi.write(b"\xff") + nblocks, err = divmod(len(buf), 512) + assert nblocks and not err, "Buffer length is invalid" + if nblocks == 1: + # CMD24: set write address for single block + if self.cmd(24, block_num * self.cdv, 0) != 0: + raise OSError(5) # EIO + self.write(_TOKEN_DATA, buf) + else: + # CMD25: set write address for first block + if self.cmd(25, block_num * self.cdv, 0) != 0: + raise OSError(5) # EIO + offset = 0 + mv = memoryview(buf) + while nblocks: + self.write(_TOKEN_CMD25, mv[offset : offset + 512]) + offset += 512 + nblocks -= 1 + self.write_token(_TOKEN_STOP_TRAN) + + def ioctl(self, op, arg): + if op == 4: # get number of blocks + return self.sectors + if op == 5: # get block size in bytes + return 512 diff --git a/mixly/boards/default_src/micropython/origin/build/lib/seniverse_api.py b/mixly/boards/default_src/micropython/origin/build/lib/seniverse_api.py new file mode 100644 index 00000000..3d8beae2 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/seniverse_api.py @@ -0,0 +1,217 @@ +""" +Seniverse Weather API + +MicroPython library for Seniverse Weather API +======================================================= + +#Preliminary composition 20220420 +#https://www.seniverse.com/api + +dahanzimin From the Mixly Team +""" + +import json +import urequests + +_weather_now="http://api.seniverse.com/v3/weather/now.json?" #天气实况 +_weather_daily="http://api.seniverse.com/v3/weather/daily.json?" #逐日天气预报 +_weather_hourly="http://api.seniverse.com/v3/weather/hourly.json?" #逐时天气预报 +_weather_alarm="http://api.seniverse.com/v3/weather/alarm.json?" #气象灾害预警 +_life_suggestion="http://api.seniverse.com/v3/life/suggestion.json?" #生活指数 +_air_now="http://api.seniverse.com/v3/air/now.json?" #空气质量实况 +_air_daily="http://api.seniverse.com/v3/air/daily.json?" #逐日空气质量预报 +_air_hourly="http://api.seniverse.com/v3/air/hourly.json?" #逐时空气质量预报 +_tide_daily="http://api.seniverse.com/v3/tide/daily.json?" #逐时潮汐预报 +_geo_sun="http://api.seniverse.com/v3/geo/sun.json?" #日出日落 +_geo_moon="http://api.seniverse.com/v3/geo/moon.json?" #月出月落和月相 +_location_search="http://api.seniverse.com/v3/location/search.json?" #城市搜索 + +#数据请求 +class API_BASE: + _results = None + def _urequests_api(self, url): + try: + results=json.loads(urequests.post(url).text) + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected",e) + + if "status" in results.keys(): + raise ValueError(results["status"]) + if "results" in results.keys(): + return results["results"] + +#天气实况 https://docs.seniverse.com/api/weather/now.html +class Weather_now(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}".format(_weather_now, key, location) + self._results = self._urequests_api(url)[0]['now'] + + def analysis(self, key=None): + if key is None: + return self._results + else: + return self._results[key] + +Weather_now = Weather_now() + +#逐日天气预报 https://docs.seniverse.com/api/weather/daily.html +class Weather_daily(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_weather_daily, key, location, days) + self._results = self._urequests_api(url)[0]['daily'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Weather_daily = Weather_daily() + +#逐时天气预报 https://docs.seniverse.com/api/weather/hourly.html +class Weather_hourly(API_BASE): + def request(self, key, location, hours=1): + url = "{}key={}&location={}&hours={}".format(_weather_hourly, key, location, hours) + self._results = self._urequests_api(url)[0]['hourly'] + + def analysis(self, hours=1, key=None): + if key is None: + return self._results[hours] + else: + return self._results[hours][key] + +#Weather_hourly = Weather_hourly() #暂不开启 + +#空气质量实况 https://docs.seniverse.com/api/air/now.html +class Air_now(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}&scope=city".format(_air_now, key, location) + self._results = self._urequests_api(url)[0]['air']['city'] + + def analysis(self, key=None): + if key is None: + return self._results + else: + return self._results[key] + +Air_now = Air_now() + +#逐日空气质量预报 https://docs.seniverse.com/api/air/daily5d.html +class Air_daily(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_air_daily, key, location, days) + self._results = self._urequests_api(url)[0]['daily'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Air_daily= Air_daily() + +#逐时空气质量预报 https://docs.seniverse.com/api/air/hourly5d.html +class Air_hourly(API_BASE): + def request(self, key, location, hours=1): + url = "{}key={}&location={}&hours={}&days=1".format(_air_hourly, key, location, hours) + self._results = self._urequests_api(url)[0]['hourly'] + + def analysis(self, hours=1, key=None): + if key is None: + return self._results[hours] + else: + return self._results[hours][key] + +#Air_hourly = Air_hourly() #暂不开启 + +#气象灾害预警 https://docs.seniverse.com/api/weather/alarm.html +class Weather_alarm(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}".format(_weather_alarm, key, location) + results = self._urequests_api(url)[0]['alarms'] + self._results = results[0] if results else {} + + def analysis(self, key=None): + if key is None: + return self._results + if key in self._results.keys(): + return self._results[key] + +Weather_alarm = Weather_alarm() + +#生活指数 https://docs.seniverse.com/api/life/suggestion.html +class Life_suggestion(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}".format(_life_suggestion, key, location) + self._results = self._urequests_api(url)[0]['suggestion'] + + def analysis(self, key=None, brief=False): + if key is None: + return self._results + else: + return self._results[key]['brief'] if brief else self._results[key]['details'] + +Life_suggestion = Life_suggestion() + +#24时潮汐预报 https://docs.seniverse.com/api/ocean/tide.html +class Tide_daily(API_BASE): + def request(self, key, location): + url = "{}key={}&location={}&days=1".format(_tide_daily, key, location) + self._results = self._urequests_api(url)[0]['ports'][0]['data'][0] + + def analysis(self, key=None): + if key is None: + return self._results + else: + key = key.split(',') + if len(key) == 1: + return self._results[key[0]] + if len(key) == 2: + return self._results['range'][int(key[0])][key[1]] + +Tide_daily = Tide_daily() + +#日出日落 https://docs.seniverse.com/api/geo/sun.html +class Geo_sun(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_geo_sun, key, location, days) + self._results = self._urequests_api(url)[0]['sun'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Geo_sun = Geo_sun() + +#月出月落和月相 https://docs.seniverse.com/api/geo/moon.html +class Geo_moon(API_BASE): + def request(self, key, location, days=1): + url = "{}key={}&location={}&days={}".format(_geo_moon, key, location, days) + self._results = self._urequests_api(url)[0]['moon'] + + def analysis(self, days=1, key=None): + if key is None: + return self._results[days] + else: + return self._results[days][key] + +Geo_moon = Geo_moon() + +#城市搜索 https://docs.seniverse.com/api/fct/search.html +class Location_search(API_BASE): + def request(self, key, location): + url = "{}key={}&q={}&limit=50".format(_location_search, key, location) + results = self._urequests_api(url) + self._results = results[0] if results else {} + + def analysis(self, key=None): + if key is None: + return self._results + else: + if key in self._results.keys(): + return self._results[key] + +Location_search = Location_search() + \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/servo.py b/mixly/boards/default_src/micropython/origin/build/lib/servo.py new file mode 100644 index 00000000..db5dacab --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/servo.py @@ -0,0 +1,53 @@ +""" +Servo + +MicroPython library for the Servo(0~180°) +======================================================= + +#Preliminary composition 20220803 + +dahanzimin From the Mixly Team +""" +from machine import Pin,PWM + +class Servo: + __species = {} + __first_init = True + + def __new__(cls, pin, *args, **kwargs): + if pin not in cls.__species.keys(): + cls.__first_init = True + cls.__species[pin]=object.__new__(cls) + return cls.__species[pin] + + def __init__(self,pin): + if self.__first_init: + self.__first_init = False + self._pulse=None + self.pwm = PWM(Pin(pin), duty=0, freq=50) + + def servo_write(self,pulse): + self._pulse=pulse + self.pwm.duty_u16(int(1638.375 + 6553.5 * pulse)) + + def servo_read(self): + return self._pulse + +#-------Method usage of class-------- + +def servo180_angle(pin,angle=None): + if angle is None: + return int(Servo(pin).servo_read()*180) + else: + if not 0<= angle <= 180: + raise ValueError("The effective range of the servo(180) angle is 0~180°") + Servo(pin).servo_write(angle/180) + + +def servo360_speed(pin,speed=None): + if speed is None: + return int(Servo(pin).servo_read()*200-100) + else: + if not -100<= speed <= 100: + raise ValueError("The effective range of the servo(360) speed is -100~100%") + Servo(pin).servo_write((speed+100)/200) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/sht20.py b/mixly/boards/default_src/micropython/origin/build/lib/sht20.py new file mode 100644 index 00000000..adc44a0d --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/sht20.py @@ -0,0 +1,37 @@ +from struct import unpack as unp +from time import sleep_ms + +# SHT20 default address +SHT20_I2CADDR = 64 +TRI_T_MEASURE_NO_HOLD = b'\xf3' +TRI_RH_MEASURE_NO_HOLD = b'\xf5' +READ_USER_REG = b'\xe7' +WRITE_USER_REG = b'\xe6' +SOFT_RESET = b'\xfe' + +class SHT20(object): + def __init__(self, i2c_bus): + self._address = SHT20_I2CADDR + self._bus = i2c_bus + + def get_SHT_temperature(self): + self._bus.writeto(self._address, TRI_T_MEASURE_NO_HOLD) + sleep_ms(150) + origin_data = self._bus.readfrom(self._address, 2) + origin_value = unp('>h', origin_data)[0] + value = -46.85 + 175.72 * (origin_value / 65536) + return value + + def get_SHT_relative_humidity(self): + self._bus.writeto(self._address, TRI_RH_MEASURE_NO_HOLD) + sleep_ms(150) + origin_data = self._bus.readfrom(self._address, 2) + origin_value = unp('>H', origin_data)[0] + value = -6 + 125 * (origin_value / 65536) + return value + + def humidity(self): + return self.get_SHT_relative_humidity() + + def temperature(self): + return self.get_SHT_temperature() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/shtc3.py b/mixly/boards/default_src/micropython/origin/build/lib/shtc3.py new file mode 100644 index 00000000..eb2e45f7 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/shtc3.py @@ -0,0 +1,134 @@ +""" +SHTC3 + +MicroPython library for the SHTC3(Humidity and Temperature) +======================================================= + +#Preliminary composition 20220224 +#https://github.com/adafruit/Adafruit_CircuitPython_SHTC3.git + +dahanzimin From the Mixly Team +""" + +from time import sleep +from micropython import const +from struct import unpack_from + +_SHTC3_DEFAULT_ADDR = const(0x70) # SHTC3 I2C Address +_SHTC3_READID = const(0xEFC8) # Read Out of ID Register +_SHTC3_SOFTRESET = const(0x805D) # Soft Reset +_SHTC3_SLEEP = const(0xB098) # Enter sleep mode +_SHTC3_WAKEUP = const(0x3517) # Wakeup mode +_SHTC3_CHIP_ID = const(0x807) +_SHTC3_NORMAL_MEAS = const(0x7866) +_SHTC3_LOWPOW_MEAS = const(0x609C) + +class SHTC3: + def __init__(self, i2c_bus, addr = _SHTC3_DEFAULT_ADDR): + self._device= i2c_bus + self._address = addr + self._buffer = bytearray(6) + self.low_power = False + self.sleeping = False + self.reset() + if self._get_chip_id() != _SHTC3_CHIP_ID: + raise AttributeError("Cannot find a SHTC3") + + def _write_command(self, command): + """helper function to write a command to the i2c device""" + self._buffer[0] = command >> 8 + self._buffer[1] = command & 0xFF + self._device.writeto(self._address,self._buffer[0:2]) + + def _get_chip_id(self): # readCommand(SHTC3_READID, data, 3); + """Determines the chip id of the sensor""" + self._write_command(_SHTC3_READID) + sleep(0.001) + self._device.readfrom_into(self._address,self._buffer) + return unpack_from(">H", self._buffer)[0] & 0x083F + + def reset(self): + """Perform a soft reset of the sensor, resetting all settings to their power-on defaults""" + self.sleeping = False + try: + self._write_command(_SHTC3_SOFTRESET) + + except RuntimeError as run_err: + if run_err.args and run_err.args[0] != "I2C device address was NACK'd": + raise run_err + sleep(0.001) + + @property + def sleeping(self): + """Determines the sleep state of the sensor""" + return self._cached_sleep + + @sleeping.setter + def sleeping(self, sleep_enabled): + if sleep_enabled: + self._write_command(_SHTC3_SLEEP) + else: + self._write_command(_SHTC3_WAKEUP) + sleep(0.001) + self._cached_sleep = sleep_enabled + + @property + def low_power(self): + """Enables the less accurate low power mode, trading accuracy for power consumption""" + return self._low_power + + @low_power.setter + def low_power(self, low_power_enabled): + self._low_power = low_power_enabled + + @property + def measurements(self): + """both `temperature` and `relative_humidity`, read simultaneously""" + self.sleeping = False + temperature = None + humidity = None + if self.low_power: + self._write_command(_SHTC3_LOWPOW_MEAS) + sleep(0.001) + else: + self._write_command(_SHTC3_NORMAL_MEAS) + sleep(0.013) + + self._device.readfrom_into(self._address,self._buffer) + + temp_data = self._buffer[0:2] + temp_crc = self._buffer[2] + humidity_data = self._buffer[3:5] + humidity_crc = self._buffer[5] + + if temp_crc != self._crc8(temp_data) or humidity_crc != self._crc8(humidity_data): + return + + raw_temp = unpack_from(">H", temp_data)[0] + raw_temp = ((4375 * raw_temp) >> 14) - 4500 + temperature = raw_temp / 100.0 + raw_humidity = unpack_from(">H", humidity_data)[0] + raw_humidity = (625 * raw_humidity) >> 12 + humidity = raw_humidity / 100.0 + + self.sleeping = True + return (temperature, humidity) + + @staticmethod + def _crc8(buffer): + """verify the crc8 checksum""" + crc = 0xFF + for byte in buffer: + crc ^= byte + for _ in range(8): + if crc & 0x80: + crc = (crc << 1) ^ 0x31 + else: + crc = crc << 1 + return crc & 0xFF # return the bottom 8 bits + + def humidity(self): + return self.measurements[1] + + def temperature(self): + return self.measurements[0] diff --git a/mixly/boards/default_src/micropython/origin/build/lib/sonar.py b/mixly/boards/default_src/micropython/origin/build/lib/sonar.py new file mode 100644 index 00000000..6b8e6ba4 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/sonar.py @@ -0,0 +1,39 @@ +""" +CS100/HC-SR04 + +Micropython library for the CS100/HC-SR04(Ultrasonic ranging) +======================================================= +@dahanzimin From the Mixly Team +""" +from time import sleep_us +from machine import Pin, time_pulse_us + +class Sonar: + __species = {} + __first_init = True + + def __new__(cls, trig, echo, *args, **kwargs): + if (trig, echo) not in cls.__species.keys(): + cls.__first_init = True + cls.__species[(trig, echo) ] = object.__new__(cls) + return cls.__species[(trig, echo)] + + def __init__(self, trig, echo, max_rang=400): + if self.__first_init: + self.__first_init = False + self.trig = Pin(trig, Pin.OUT, value=0) + self.echo = Pin(echo, Pin.IN) + self.timeout_us = int(max_rang * 2 * 29.1) + + def checkdist(self): + self.trig.value(0) + sleep_us(5) + self.trig.value(1) + sleep_us(10) + self.trig.value(0) + try: + pulse_time = time_pulse_us(self.echo, 1, self.timeout_us) + pulse_time = pulse_time if pulse_time >= 0 else self.timeout_us + return round(pulse_time / 2 / 29.1, 2) # 1cm each 29.1us + except: + return None diff --git a/mixly/boards/default_src/micropython/origin/build/lib/spl06_001.py b/mixly/boards/default_src/micropython/origin/build/lib/spl06_001.py new file mode 100644 index 00000000..c291c0a6 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/spl06_001.py @@ -0,0 +1,115 @@ +""" +_SPL06-001 + +MicroPython library for the _SPL06-001(Air pressure sensor) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +_SPL06_ADDRESS = const(0x77) +_SPL06_REG_PSR = const(0x00) +_SPL06_REG_TMP = const(0x03) +_SPL06_PSR_CFG = const(0x06) +_SPL06_TMP_CFG = const(0x07) +_SPL06_MEAS_CFG = const(0x08) +_SPL06_CFG_REG = const(0x09) +_SPL06_REG_RST = const(0x0C) +_SPL06_REG_ID = const(0x0D) +_SPL06_REG_COEF = const(0x10) + +#Parameter selection(sample/sec, times, kT/kP) +_SPL06_PSR_TMP_1 = (0<<4, 0, 524288) +_SPL06_PSR_TMP_2 = (1<<4, 1, 1572864) +_SPL06_PSR_TMP_4 = (2<<4, 2, 3670016) +_SPL06_PSR_TMP_8 = (3<<4, 3, 7864320) +_SPL06_PSR_TMP_16 = (4<<4, 4, 253952) +_SPL06_PSR_TMP_32 = (5<<4, 5, 516096) +_SPL06_PSR_TMP_64 = (6<<4, 6, 1040384) +_SPL06_PSR_TMP_128 = (7<<4, 7, 2088960) + +class SPL06: + def __init__(self, i2c_bus, addr=_SPL06_ADDRESS, rate=_SPL06_PSR_TMP_32): + self._device = i2c_bus + self._address = addr + self._rate = rate + self._psr = 0 + self._tmp = 0 + self._alt = 0 + if self._rreg(_SPL06_REG_ID) != 0x10: + raise AttributeError("Cannot find a SPL06-001") + self._init() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _u2s(self, value, n=8): + return value if value < (1 << (n-1)) else value - (1 << n) + + def _status(self): + '''数据转换状态''' + status = self._rreg(_SPL06_MEAS_CFG) + return status & 0x80, status & 0x40, (status >> 4 & 0x01) & (status >> 5 & 0x01) #COEF_RDY,SENSOR_RDY,TMP_RDY+PRS_RDY + + def _init(self): + '''软复位''' + self._wreg(_SPL06_REG_RST, 0x89) + time.sleep_ms(50) + '''判断校准数据是否就绪,并读取''' + while not self._status()[0]: + time.sleep_ms(1) + buf = self._rreg(_SPL06_REG_COEF, 18) + self._c0 = self._u2s(buf[0] << 4 | buf[1] >> 4, 12) + self._c1 = self._u2s((buf[1] & 0x0F) << 8 | buf[2], 12) + self._c00 = self._u2s(buf[3] << 12 | buf[4] << 4 | buf[5] >> 4, 20) + self._c10 = self._u2s((buf[5] & 0x0F) << 16 | buf[6] << 8 | buf[7], 20) + self._c01 = self._u2s(buf[8] << 8 | buf[9], 16) + self._c11 = self._u2s(buf[10] << 8 | buf[11], 16) + self._c20 = self._u2s(buf[12] << 8 | buf[13], 16) + self._c21 = self._u2s(buf[14] << 8 | buf[15], 16) + self._c30 = self._u2s(buf[16] << 8 | buf[17], 16) + + '''判断传感器是否就绪,并设置''' + while not self._status()[1]: + time.sleep_ms(1) + self._wreg(_SPL06_MEAS_CFG, 0x07) #Continuous pressure and temperature + self._wreg(_SPL06_PSR_CFG, self._rate[0] | self._rate[1]) #Configuration of pressure measurement. + self._wreg(_SPL06_TMP_CFG, self._rate[0] | self._rate[1] | 0x80) #Configuration of temperature measurement. + self._rreg(_SPL06_REG_PSR, 6) + + if self._rate[1] > 3: + self._wreg(_SPL06_CFG_REG, self._rreg(_SPL06_CFG_REG) | 0x0C) #when the oversampling rate is >8 times. + + ''''判断数据是否就绪,并读取''' + #while not self._status()[2]: + #time.sleep_ms(1) #数据就绪需要耗时1s左右 + + @property + def getdata(self): + '''处理获取数据''' + if self._status()[2]: + buf = self._rreg(_SPL06_REG_PSR, 6) + praw = self._u2s(buf[0] << 16 | buf[1] << 8 | buf[2], 24) / self._rate[2] + traw = self._u2s(buf[3] << 16 | buf[4] << 8 | buf[5], 24) / self._rate[2] + try: + self._psr = self._c00 + praw * (self._c10 + praw *(self._c20 + praw * self._c30)) + traw * self._c01 + traw * praw * (self._c11 + praw * self._c21) + except: + self._psr = 0 + self._tmp = self._c0 * 0.5 + self._c1 * traw + self._alt = (1 - (self._psr / 101325) ** (1/5.255)) * 44330 + return round(self._psr/100, 2), round(self._tmp, 2), round(self._alt,2) + + def pressure(self): + return self.getdata[0] + + def temperature(self): + return self.getdata[1] + + def altitude(self, reference=1013.25): + return round((pow((reference / 33.8639), 0.190255) - pow((self.getdata[0] / 33.8639), 0.190255)) / 0.000013125214, 2) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ssd1106.py b/mixly/boards/default_src/micropython/origin/build/lib/ssd1106.py new file mode 100644 index 00000000..a4d2e810 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ssd1106.py @@ -0,0 +1,124 @@ +""" +SSD1106 + +library for the SSD1x06 OLED128x64 +======================================================= +@dahanzimin From the Mixly Team +""" +import uframebuf +from micropython import const + +SET_CONTRAST = const(0x81) +SET_ENTIRE_ON = const(0xa4) +SET_NORM_INV = const(0xa6) +SET_DISP_OFF = const(0xae) +SET_DISP_ON = const(0xaf) +SET_MEM_ADDR = const(0x20) +SET_PAGE_ADDR = const(0x22) +SET_DISP_START_LINE = const(0x40) +SET_SEG_REMAP = const(0xa0) +SET_MUX_RATIO = const(0xa8) +SET_COM_OUT_DIR = const(0xc0) +SET_DISP_OFFSET = const(0xd3) +SET_COM_PIN_CFG = const(0xda) +SET_DISP_CLK_DIV = const(0xd5) +SET_PRECHARGE = const(0xd9) +SET_VCOM_DESEL = const(0xdb) +SET_CHARGE_PUMP = const(0x8d) +SET_COL_ADDR_L = const(0x02) +SET_COL_ADDR_H = const(0x10) +SET_PAGE_ADDR1 = const(0xb0) +SET_CONTRACT_CTRL = const(0x81) + +class SSD1106(uframebuf.FrameBuffer_Uincode): + def __init__(self, width, height, external_vcc, l_offset=0, h_offset=0): + self._external = external_vcc + self._l_offset = l_offset + self._h_offset = h_offset + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_VLSB) + self.init_display() + + def init_display(self): + for cmd in ( + SET_DISP_OFF, # display off + SET_DISP_CLK_DIV, 0x80, # timing and driving scheme + SET_MUX_RATIO, 0x3f, #0xa8 + SET_DISP_OFFSET, 0x00, #0xd3 + SET_DISP_START_LINE | 0x00, #start line + SET_CHARGE_PUMP, 0x10 if self._external else 0x14, + SET_MEM_ADDR, 0x00, # address setting + SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0 + SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0 + SET_COM_PIN_CFG, 0x12, + SET_CONTRACT_CTRL, 0xcf, + SET_PRECHARGE, 0x22 if self._external else 0xf1, + SET_VCOM_DESEL, 0x40, # 0.83*Vcc + SET_ENTIRE_ON, # output follows RAM contents + SET_NORM_INV, + SET_DISP_ON): # on + self.write_cmd(cmd) + self.fill(0) + self.show() + + def poweroff(self): + self.write_cmd(SET_DISP_OFF) + + def poweron(self): + self.write_cmd(SET_DISP_ON) + + def contrast(self, contrast): + self.write_cmd(SET_CONTRAST) + self.write_cmd(contrast) + + def invert(self, invert): + self.write_cmd(SET_NORM_INV | (invert & 1)) + + def show(self): + for i in range(0, 8): + self.write_cmd(SET_PAGE_ADDR1 + i) + self.write_cmd(SET_COL_ADDR_L + self._l_offset) + self.write_cmd(SET_COL_ADDR_H + self._h_offset) + self.write_data(self._buffer[i * 128:(i + 1) * 128]) #send one page display data + +class SSD1106_I2C(SSD1106): + def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False, l_offset=0, h_offset=0): + self.i2c = i2c + self.addr = addr + self.temp = bytearray(2) + super().__init__(width, height, external_vcc, l_offset, h_offset) + + def write_cmd(self, cmd): + self.temp[0] = 0x80 + self.temp[1] = cmd + self.i2c.writeto(self.addr, self.temp) + + def write_data(self, buf): + tmp = bytearray([0x40]) + self.i2c.writeto(self.addr, tmp+buf) + +class SSD1106_SPI(SSD1106): + def __init__(self, width, height, spi, dc, cs, external_vcc=False, l_offset=0, h_offset=0): + self.rate = 10 * 1024 * 1024 + dc.init(dc.OUT, value=0) + cs.init(cs.OUT, value=1) + self.spi = spi + self.dc = dc + self.cs = cs + super().__init__(width, height, external_vcc, l_offset, h_offset) + + def write_cmd(self, cmd): + self.spi.init(baudrate=self.rate, polarity=0, phase=0) + self.cs(1) + self.dc(0) + self.cs(0) + self.spi.write(bytearray([cmd])) + self.cs(1) + + def write_data(self, buf): + self.spi.init(baudrate=self.rate, polarity=0, phase=0) + self.cs(1) + self.dc(1) + self.cs(0) + self.spi.write(buf) + self.cs(1) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/st7735.py b/mixly/boards/default_src/micropython/origin/build/lib/st7735.py new file mode 100644 index 00000000..557b38f7 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/st7735.py @@ -0,0 +1,117 @@ +""" +ST7735 + +MicroPython library for the ST7735(TFT-SPI) +======================================================= +#Preliminary composition 20230822 + +@dahanzimin From the Mixly Team +""" +import time, uframebuf +from machine import Pin, PWM +from micropython import const + +_CMD_SWRESET = const(0x01) +_CMD_SLPOUT = const(0x11) +_CMD_PTLON = const(0x12) +_CMD_NORON = const(0x13) +_CMD_INVOFF = const(0x20) +_CMD_INVON = const(0x21) +_CMD_DISPOFF = const(0x28) +_CMD_DISPON = const(0x29) +_CMD_CASET = const(0x2A) +_CMD_RASET = const(0x2B) +_CMD_RAMWR = const(0x2C) +_CMD_RAMRD = const(0x2E) +_CMD_PTLAR = const(0x30) +_CMD_COLMOD = const(0x3A) +_CMD_MADCTL = const(0x36) +_CMD_FRMCTR1 = const(0xB1) +_CMD_FRMCTR2 = const(0xB2) +_CMD_FRMCTR3 = const(0xB3) +_CMD_INVCTR = const(0xB4) +_CMD_PWCTR1 = const(0xC0) +_CMD_PWCTR2 = const(0xC1) +_CMD_PWCTR3 = const(0xC2) +_CMD_PWCTR4 = const(0xC3) +_CMD_PWCTR5 = const(0xC4) +_CMD_VMCTR1 = const(0xC5) +_CMD_GMCTRP1 = const(0xE0) +_CMD_GMCTRN1 = const(0xE1) + +class ST7735(uframebuf.FrameBuffer_Uincode): + def __init__(self, spi, width, height, dc_pin=None, cs_pin=None, bl_pin=None, font_address=0x700000, rotation=0): + self.spi = spi + self.dc = Pin(dc_pin, Pin.OUT, value=1) + self.cs = Pin(cs_pin, Pin.OUT, value=1) + self._buffer = bytearray(width * height * 2) + super().__init__(self._buffer, width, height, uframebuf.RGB565) + self.font(font_address) + self._init() + self.rotation(rotation) + self.fill(0) + self.show() + time.sleep_ms(100) + self._brightness = 0.6 + self.bl_led = PWM(Pin(bl_pin), duty_u16=int(self._brightness * 60000)) if bl_pin else None + + def _write(self, cmd, dat = None): + self.cs.off() + self.dc.off() + self.spi.write(bytearray([cmd])) + self.cs.on() + if dat is not None: + self.cs.off() + self.dc.on() + self.spi.write(dat) + self.cs.on() + + def _init(self): + """Display initialization configuration""" + for cmd, data, delay in [ + (_CMD_SWRESET, None, 100), + (_CMD_SLPOUT, None, 200), + (_CMD_FRMCTR1, b'\x01\x2c\x2d', 10), + (_CMD_FRMCTR2, b'\x01\x2c\x2d', 10), + (_CMD_FRMCTR3, b'\x01\x2c\x2d', 10), + (_CMD_INVCTR, b'\x07', None), + (_CMD_PWCTR1, b'\xa2\x02\x84', 10), + (_CMD_PWCTR2, b'\xc5', None), + (_CMD_PWCTR3, b'\x0a\x00', None), + (_CMD_PWCTR4, b'\x8a\x2a', None), + (_CMD_PWCTR5, b'\x8a\xee', None), + (_CMD_VMCTR1, b'\x0e', None), + (_CMD_GMCTRP1, b'\x02\x1c\x07\x12\x37\x32\x29\x2d\x29\x25\x2b\x39\x00\x01\x03\x10', None), + (_CMD_GMCTRN1, b'\x03\x1d\x07\x06\x2e\x2c\x29\x2d\x2e\x2e\x37\x3f\x00\x00\x02\x10', None), + (_CMD_COLMOD, b'\x05', 10), + (_CMD_NORON, None, 10), + (_CMD_DISPON, None, 200), + ]: + self._write(cmd, data) + if delay: + time.sleep_us(delay) + + def rotation(self, rotation): + self._write(_CMD_MADCTL, b'\x60') if rotation else self._write(_CMD_MADCTL, b'\xa0') + self._write(_CMD_CASET, b'\x01\x01\x01\xa0') + self._write(_CMD_RASET, b'\x02\x02\x02\x81') + + def get_brightness(self): + return self._brightness + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0~1.0") + self._brightness = brightness + self.bl_led.duty_u16(int(brightness*60000)) + + def color(self, red, green=None, blue=None): + """ Convert red, green and blue values (0-255) into a 16-bit 565 encoding.""" + if green is None or blue is None: + return red + else: + return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3 + + def show(self): + """Refresh the display and show the changes.""" + self._write(_CMD_RAMWR, self._buffer) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/st7789.py b/mixly/boards/default_src/micropython/origin/build/lib/st7789.py new file mode 100644 index 00000000..638c9255 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/st7789.py @@ -0,0 +1,330 @@ +""" +ST7789 + +MicroPython library for the ST7789(TFT-SPI) +======================================================= +#Preliminary composition 20220830 +#https://github.com/russhughes/st7789py_mpy + +dahanzimin From the Mixly Team +""" + +import time +from machine import Pin +from micropython import const +from uframebuf import Font_Uincode, Image +import ustruct as struct + + +ST7789_NOP = const(0x00) +ST7789_SWRESET = const(0x01) +ST7789_RDDID = const(0x04) +ST7789_RDDST = const(0x09) +ST7789_SLPIN = const(0x10) +ST7789_SLPOUT = const(0x11) +ST7789_PTLON = const(0x12) +ST7789_NORON = const(0x13) +ST7789_INVOFF = const(0x20) +ST7789_INVON = const(0x21) +ST7789_DISPOFF = const(0x28) +ST7789_DISPON = const(0x29) +ST7789_CASET = const(0x2A) +ST7789_RASET = const(0x2B) +ST7789_RAMWR = const(0x2C) +ST7789_RAMRD = const(0x2E) +ST7789_PTLAR = const(0x30) +ST7789_VSCRDEF = const(0x33) +ST7789_COLMOD = const(0x3A) +ST7789_MADCTL = const(0x36) +ST7789_VSCSAD = const(0x37) +ST7789_MADCTL_MY = const(0x80) +ST7789_MADCTL_MX = const(0x40) +ST7789_MADCTL_MV = const(0x20) +ST7789_MADCTL_ML = const(0x10) +ST7789_MADCTL_BGR = const(0x08) +ST7789_MADCTL_MH = const(0x04) +ST7789_MADCTL_RGB = const(0x00) +ST7789_RDID1 = const(0xDA) +ST7789_RDID2 = const(0xDB) +ST7789_RDID3 = const(0xDC) +ST7789_RDID4 = const(0xDD) +COLOR_MODE_65K = const(0x50) +COLOR_MODE_262K = const(0x60) +COLOR_MODE_12BIT = const(0x03) +COLOR_MODE_16BIT = const(0x05) +COLOR_MODE_18BIT = const(0x06) +COLOR_MODE_16M = const(0x07) + +# Color definitions +BLACK = const(0x0000) +BLUE = const(0x001F) +RED = const(0xF800) +GREEN = const(0x07E0) +CYAN = const(0x07FF) +MAGENTA = const(0xF81F) +YELLOW = const(0xFFE0) +WHITE = const(0xFFFF) + +_BUFFER_SIZE = const(256) + +# Rotation tables (width, height, xstart, ystart)[rotation % 4] +WIDTH_320 = [(240, 320, 0, 0),(320, 240, 0, 0),(240, 320, 0, 0),(320, 240, 0, 0)] +WIDTH_240 = [(240, 240, 0, 0),(240, 240, 0, 0),(240, 240, 0, 80),(240, 240, 80, 0)] +WIDTH_135 = [(135, 240, 52, 40),(240, 135, 40, 53),(135, 240, 53, 40),(240, 135, 40, 52)] + +ROTATIONS = [0x00, 0x60, 0xc0, 0xa0] + +def color565(red, green=0, blue=0): + """ Convert red, green and blue values (0-255) into a 16-bit 565 encoding.""" + try: + red, green, blue = red # see if the first var is a tuple/list + except TypeError: + pass + return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3 + +def _encode_pos(x, y): + """Encode a postion into bytes.""" + return struct.pack(">HH", x, y) + +def _encode_pixel(color): + """Encode a pixel color into bytes.""" + return struct.pack(">H", color) + +class ST7789(): + def __init__(self, spi, width, height, dc_pin=None,cs_pin=None, rotation=0, font_address=0x700000): + if height != 240 or width not in [320, 240, 135]: + raise ValueError("Unsupported display. 320x240, 240x240 and 135x240 are supported.") + + self._font= Font_Uincode(font_address) + self._image= Image() + self._display_width = self.width = width + self._display_height = self.height = height + self.xstart = 0 + self.ystart = 0 + self.spi = spi + self.spi.init(polarity=1) + self.dc = Pin(dc_pin, Pin.OUT) + self.cs = Pin(cs_pin, Pin.OUT) + self._rotation = rotation % 4 + self.soft_reset() + self.sleep_mode(False) + + self._set_color_mode(COLOR_MODE_65K | COLOR_MODE_16BIT) + time.sleep_ms(50) + self.rotation(self._rotation) + self.inversion_mode(True) + time.sleep_ms(10) + self._write(ST7789_NORON) + time.sleep_ms(10) + self.fill(0) + self._write(ST7789_DISPON) + time.sleep_ms(500) + + def _write(self, command=None, data=None): + """SPI write to the device: commands and data.""" + if self.cs: + self.cs.off() + if command is not None: + self.dc.off() + self.spi.write(bytes([command])) + if data is not None: + self.dc.on() + self.spi.write(data) + if self.cs: + self.cs.on() + + def soft_reset(self): + """Soft reset display.""" + self._write(ST7789_SWRESET) + time.sleep_ms(150) + + def sleep_mode(self, value): + """Enable or disable display sleep mode.""" + if value: + self._write(ST7789_SLPIN) + else: + self._write(ST7789_SLPOUT) + + def inversion_mode(self, value): + """Enable or disable display inversion mode.""" + if value: + self._write(ST7789_INVON) + else: + self._write(ST7789_INVOFF) + + def _set_color_mode(self, mode): + """ Set display color mode. """ + self._write(ST7789_COLMOD, bytes([mode & 0x77])) + + def rotation(self, rotation): + """Set display rotation.""" + rotation %= 4 + self._rotation = rotation + madctl = ROTATIONS[rotation] + + if self._display_width == 320: + table = WIDTH_320 + elif self._display_width == 240: + table = WIDTH_240 + elif self._display_width == 135: + table = WIDTH_135 + else: + raise ValueError("Unsupported display. 320x240, 240x240 and 135x240 are supported.") + self.width, self.height, self.xstart, self.ystart = table[rotation] + self._write(ST7789_MADCTL, bytes([madctl])) + + def _set_columns(self, start, end): + """Send CASET (column address set) command to display.""" + if start <= end <= self.width: + self._write(ST7789_CASET, _encode_pos( + start+self.xstart, end + self.xstart)) + + def _set_rows(self, start, end): + """Send RASET (row address set) command to display.""" + if start <= end <= self.height: + self._write(ST7789_RASET, _encode_pos( + start+self.ystart, end+self.ystart)) + + def _set_window(self, x0, y0, x1, y1): + """Set window to column and row address.""" + self._set_columns(x0, x1) + self._set_rows(y0, y1) + self._write(ST7789_RAMWR) + + def vline(self, x, y, length, color): + """Draw vertical line at the given location and color.""" + self.fill_rect(x, y, 1, length, color) + + def hline(self, x, y, length, color): + """Draw horizontal line at the given location and color.""" + self.fill_rect(x, y, length, 1, color) + + def pixel(self, x, y, color): + """Draw a pixel at the given location and color.""" + self._set_window(x, y, x, y) + pixel_color =_encode_pixel(color) if type(color)==int else _encode_pixel(color565(color)) + self._write(None, pixel_color) + + def blit_buffer(self, buffer, x, y, width, height): + """Copy buffer to display at the given location.""" + self._set_window(x, y, x + width - 1, y + height - 1) + self._write(None, buffer) + + def rect(self, x, y, w, h, color): + """Draw a rectangle at the given location, size and color.""" + self.hline(x, y, w, color) + self.vline(x, y, h, color) + self.vline(x + w - 1, y, h, color) + self.hline(x, y + h - 1, w, color) + + def fill_rect(self, x, y, width, height, color): + """Draw a rectangle at the given location, size and filled with color.""" + self._set_window(x, y, x + width - 1, y + height - 1) + chunks, rest = divmod(width * height, _BUFFER_SIZE) + pixel = _encode_pixel(color) if type(color)==int else _encode_pixel(color565(color)) + self.dc.on() + if chunks: + data = pixel * _BUFFER_SIZE + for _ in range(chunks): + self._write(None, data) + if rest: + self._write(None, pixel * rest) + + def fill(self, color): + """Fill the entire FrameBuffer with the specified color.""" + self.fill_rect(0, 0, self.width, self.height, color) + + def line(self, x0, y0, x1, y1, color): + """Draw a single pixel wide line starting at x0, y0 and ending at x1, y1.""" + steep = abs(y1 - y0) > abs(x1 - x0) + if steep: + x0, y0 = y0, x0 + x1, y1 = y1, x1 + if x0 > x1: + x0, x1 = x1, x0 + y0, y1 = y1, y0 + dx = x1 - x0 + dy = abs(y1 - y0) + err = dx // 2 + ystep = 1 if y0 < y1 else -1 + while x0 <= x1: + if steep: + self.pixel(y0, x0, color) + else: + self.pixel(x0, y0, color) + err -= dy + if err < 0: + y0 += ystep + err += dx + x0 += 1 + + def image(self,path, x=0, y=0, size=1, color=WHITE, invert=0): + """Set buffer to value of Python Imaging Library image""" + size=max(round(size),1) + if type(path) ==str : + buffer_info,(width, height) = self._image.load(path,invert) + elif type(path) ==bytes: + buffer_info,(width, height) = self._image.load_py(path,invert) + else: + raise ValueError("invalid input") + + self.bitmap((buffer_info,(width, height)), x, y, size, color) + + def bitmap(self,buffer, x=0, y=0, size=1, color=WHITE): + """Graphic model display(buffer,(width,height))""" + buffer_info,(width,height)=buffer + if x < -width*size or x >= self.width or y < -height*size or y >= self.height: + return #Limit reasonable display area + color_buffer = bytearray(0) + byteWidth = int((width + 7) / 8) + for j in range(height): + for i in range(width): + if buffer_info[int(j * byteWidth + i / 8)] & (0x80 >> (i & 7)): + self.fill_rect(x+i*size, y+j*size, size, size, color) + + def _take_buffer(self,strs,space,size=1): + '''Get character lattice information first''' + font_buffer=[] + font_len=0 + for c in strs: + buffer=self._font.chardata(c) + font_buffer.append(buffer) + font_len=font_len+buffer[1][0]*size+space + return font_len,font_buffer + + def shows(self,data,x=0,y=0,size=1,space=0,center=False, color=WHITE): + """Display character""" + if data: + size=max(round(size),1) + font_len,font_buffer=self._take_buffer(str(data),space,size) + x=(self.width-font_len+space)//2 if center else x + #self.fill_rect(x-1,y-1,font_len+2,font_buffer[0][1][1]*size+2,0) + for buffer in font_buffer: #Display character + self.bitmap(buffer,x,y,size,color) + x=buffer[1][0]*size+x+space + + def frame(self, data, delay=500, size=5, color=WHITE): + """Display one frame per character""" + if data: + size=max(round(size),1) + _,font_buffer=self._take_buffer(str(data),0) + for buffer in font_buffer: + x=(self.width - buffer[1][0]*size)//2 + y=(self.height - buffer[1][1]*size)//2 + self.fill_rect(x-1,y-1,buffer[1][0]*size+2,buffer[1][1]*size+2,0) + self.bitmap(buffer,x,y,size,color) + #self.show() + time.sleep_ms(delay) + + def scroll(self, data, y=0, size=1, space=0, speed=5, color=WHITE): + """Scrolling characters""" + if data: + size=max(round(size),1) + font_len,font_buffer=self._take_buffer(str(data),space,size) + for i in range(font_len-space+self.width): + x=-i+self.width + self.fill_rect(x-1,y-1,self.width-x+2,font_buffer[0][1][1]*size+2,0) + for buffer in font_buffer: + self.bitmap(buffer,x,y,size,color) + x=buffer[1][0]*size+x+space + time.sleep_ms(speed) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/syn6288.py b/mixly/boards/default_src/micropython/origin/build/lib/syn6288.py new file mode 100644 index 00000000..55763cc6 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/syn6288.py @@ -0,0 +1,83 @@ +""" +SYN6288 + +Micropython library for the SYN6288(speech synthesis) +======================================================= +#Preliminary composition 20220805 + +dahanzimin From the Mixly Team +""" +import time +from micropython import const + +REG_PLAY_SST = const(0x01) +#REG_BAUD_SST = const(0x31) +#REG_STOP_SST = const(0x02) +#REG_PAUSE_SST = const(0x03) +#REG_RESUME_SST = const(0x04) +#EG_QUERY_SST = const(0x21) +#EG_DOWN_SST = const(0x88) + +class SYN6288: + def __init__(self, uart): + self._uart=uart + self._uart.init(baudrate=9600) + self._state=False + self._volume="[v10]" + + def _wreg(self, reg, val5=0,val3=None, data=None): + '''Write memory address''' + buffer=[0xFD,0x00,0x00,reg] + eec=0 + + if not val5 is None and not val3 is None : + buffer.append((val3 & 0x07) | (val5 << 3)) + if not data is None: + for char in data: + buffer.append(ord(char) >> 8) + buffer.append(ord(char) & 0xFF) + + buffer[2]= len(buffer)-2 + for i in range(len(buffer)): + eec^=int(buffer[i]) + buffer.append(eec) + + self._uart.write(bytes(buffer)) + + def volume(self,vol=None): + if vol is None: + return int(self._volume[2:-1]) + if not 0 <= vol <= 16: + raise ValueError("The effective range of volume value is 0~16") + else: + self._volume="[v{}]".format(vol) + + def synthesis(self, data, music=0, blocking=True): + """Support uincode coded speech synthesis""" + self._wreg(REG_PLAY_SST,music,3,self._volume+str(data)) + time.sleep(0.1) + while blocking : + if not self.status(): + break + + def status(self): + """Playback status (true is playing)""" + if self._uart.any(): + state= self._uart.read() + if state==b'A': + self._state = True + if state==b'O': + self._state = False + return self._state + + def hint_tones(self,number, blocking=True): + """Play built-in prompt tone""" + if number <25: + tones="sound"+chr(ord("a")+number) + elif number <33: + tones="msg"+chr(ord("a")+number-25) + elif number <48: + tones="ring"+chr(ord("a")+number-33) + else: + raise ValueError("Input out of range") + self.synthesis(tones,blocking=blocking) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/tiny_webdb.py b/mixly/boards/default_src/micropython/origin/build/lib/tiny_webdb.py new file mode 100644 index 00000000..7ff1fde1 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/tiny_webdb.py @@ -0,0 +1,91 @@ +import urequests as requests + + +def url_quote(s): + safe = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-" + s = str(s) + res = bytearray() + for b in s.encode('utf-8'): + if b in safe: + res.append(b) + else: + res.extend(b'%' + b'%02X' % b) + return res.decode() + + +class TinyWebDB: + def __init__(self, *args): + if len(args) == 1: + self.init_with_mqtt(*args) + else: + self.init_with_user(*args) + + def init_with_user(self, url, username, password): + self._api_url = "" + self._username = username + self._password = password + self.set_url(url) + + def init_with_mqtt(self, mqtt_client): + self._api_url = "" + url, username, password = mqtt_client.get_server_info() + self.set_url('https://{}/tinydb'.format(url)) + self._username = username + self._password = password + + def update(self, key, value): + key = url_quote(str(key)) + value = url_quote(str(value)) + result = self._request("update", "tag={}&value={}".format(key, value)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + + def get(self, key): + key = url_quote(str(key)) + result = self._request("get", "tag={}".format(key)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + return result["value"] + + def count(self): + result = self._request("count") + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + return int(result["count"]) + + def search(self, no=1, count=1, tag='', dtype='both'): + no = str(no) + count = str(count) + tag = url_quote(tag) + result = self._request("search", "no={}&count={}&tag={}&type={}".format(no, count, tag, dtype)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + return result["data"] + + def delete(self, key): + key = url_quote(str(key)) + result = self._request("delete", "tag={}".format(key)) + if "status" in result and result["status"] == "error": + raise RuntimeError(result["message"]) + + def set_url(self, url): + if url[-1] != '/': + url += '/' + self._api_url = url + + def _request(self, op, param=""): + data = "user={}&secret={}&action={}".format(self._username, self._password, op) + if param: + data += '&' + param + try: + headers = { + "Content-Type": "application/x-www-form-urlencoded" + } + response = requests.post(self._api_url, data=data, headers=headers) + result = {} + if response.status_code == 200: + result = response.json() + response.close() + return result + except Exception as e: + raise RuntimeError("API request failed or WiFi is not connected", e) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/tm1637.py b/mixly/boards/default_src/micropython/origin/build/lib/tm1637.py new file mode 100644 index 00000000..287db069 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/tm1637.py @@ -0,0 +1,121 @@ +""" +TM1637 for Four Digit LED Display + +Micropython library for the TM1637 +======================================================= +@dahanzimin From the Mixly Team +""" +from machine import Pin +from time import sleep_us +from micropython import const + +TM1637_CMD1 = const(0x40) +TM1637_CMD2 = const(0xC0) +TM1637_CMD3 = const(0x80) +TM1637_DSP_ON = const(0x08) +TM1637_DELAY = const(0x0A) +_SEGMENTS = b'\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F\x77\x7C\x39\x5E\x79\x71' + +class TM1637: + def __init__(self, clk, dio, brightness=2): + self.clk = Pin(clk, Pin.OUT, value=0) + self.dio = Pin(dio, Pin.OUT, value=0) + sleep_us(TM1637_DELAY) + self._intensity = brightness + self.dbuf = [0, 0, 0, 0] + self.on() + + def _start(self): + self.dio(0) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + + def _stop(self): + self.dio(0) + sleep_us(TM1637_DELAY) + self.clk(1) + sleep_us(TM1637_DELAY) + self.dio(1) + + def _write(self, b): + for i in range(8): + self.dio((b >> i) & 1) + sleep_us(TM1637_DELAY) + self.clk(1) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + self.clk(1) + sleep_us(TM1637_DELAY) + self.clk(0) + sleep_us(TM1637_DELAY) + + def intensity(self, val=None): + """Set the display brightness 0-7.""" + if val is None: + return self._intensity + val = max(min(val, 7), 0) + self._intensity = val + if val == 0: + self.off() + else: + self.on() + + def on(self): + self._start() + self._write(TM1637_CMD1) + self._stop() + self._start() + self._write(TM1637_CMD3 | TM1637_DSP_ON | self._intensity) + self._stop() + + def off(self): + self._start() + self._write(TM1637_CMD3) + self._stop() + + def dat(self, bit, data): + self._start() + self._write(TM1637_CMD2 | bit) + self._write(data) + self._stop() + + def clear(self): + self.dat(0, 0) + self.dat(1, 0) + self.dat(2, 0) + self.dat(3, 0) + self.dbuf = [0, 0, 0, 0] + + def showbit(self, num, bit=0): + self.dbuf[bit % 4] = _SEGMENTS[num % 16] + self.dat(bit, _SEGMENTS[num % 16]) + + def shownum(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num // 1000) % 10) + self.showbit(num % 10, 3) + self.showbit((num // 10) % 10, 2) + self.showbit((num // 100) % 10, 1) + + def showhex(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num >> 12) % 16) + self.showbit(num % 16, 3) + self.showbit((num >> 4) % 16, 2) + self.showbit((num >> 8) % 16, 1) + + def showDP(self, bit=1, show=True): + if show: + self.dat(bit, self.dbuf[bit] | 0x80) + else: + self.dat(bit, self.dbuf[bit] & 0x7F) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/tm1650.py b/mixly/boards/default_src/micropython/origin/build/lib/tm1650.py new file mode 100644 index 00000000..23acc7b4 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/tm1650.py @@ -0,0 +1,83 @@ +""" +TM1650 for Four Digit LED Display + +Micropython library for the TM1650 +======================================================= +@dahanzimin From the Mixly Team +""" +from micropython import const +from machine import Pin, SoftI2C + +TM1650_CMD = const(0x24) +TM1650_DSP = const(0x34) +_SEGMENTS = b'\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F\x77\x7C\x39\x5E\x79\x71' + +class TM1650: + def __init__(self, i2c_bus=None, clk=0, dio=1, brightness=2): + if i2c_bus is None: + self.i2c = SoftI2C(scl=Pin(clk), sda=Pin(dio), freq=100000) + else: + self.i2c = i2c_bus + self._intensity = brightness + self.dbuf = [0, 0, 0, 0] + self.on() + + def _wreg(self, val): + self.i2c.writeto(TM1650_CMD, val.to_bytes(1, 'little')) + + def intensity(self, val=None): + """Set the display brightness 0-7.""" + if val is None: + return self._intensity + val = max(min(val, 7), 0) + self._intensity = val + if val == 0: + self.off() + else: + self.on() + + def on(self): + self._wreg((self._intensity << 4) | 0x01) + + def off(self): + self._wreg(0) + + def dat(self, bit, val): + self.i2c.writeto(TM1650_DSP + bit % 4, val.to_bytes(1, 'little')) + + def clear(self): + self.dat(0, 0) + self.dat(1, 0) + self.dat(2, 0) + self.dat(3, 0) + self.dbuf = [0, 0, 0, 0] + + def showbit(self, num, bit=0): + self.dbuf[bit % 4] = _SEGMENTS[num % 16] + self.dat(bit, _SEGMENTS[num % 16]) + + def shownum(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num // 1000) % 10) + self.showbit(num % 10, 3) + self.showbit((num // 10) % 10, 2) + self.showbit((num // 100) % 10, 1) + + def showhex(self, num): + if num < 0: + self.dat(0, 0x40) # '-' + num = -num + else: + self.showbit((num >> 12) % 16) + self.showbit(num % 16, 3) + self.showbit((num >> 4) % 16, 2) + self.showbit((num >> 8) % 16, 1) + + def showDP(self, bit=1, show=True): + if show: + self.dat(bit, self.dbuf[bit] | 0x80) + else: + self.dat(bit, self.dbuf[bit] & 0x7F) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/tm1652.py b/mixly/boards/default_src/micropython/origin/build/lib/tm1652.py new file mode 100644 index 00000000..c9b96685 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/tm1652.py @@ -0,0 +1,78 @@ +""" +TM1652-framebuf + +Micropython library for the TM1652 Matrix8x5 +======================================================= + +#Preliminary composition 20230126 + +@dahanzimin From the Mixly Team +""" +import time +import uframebuf +from machine import Pin +from micropython import const + +_TM1652_REG_ADD = const(0x08) #Display address command +_TM1652_REG_CMD = const(0x18) #Display control command +_TM1652_SET_CUR = const(0x04) #LED current setting 3/8 + +class TM1652(uframebuf.FrameBuffer_Ascall): + def __init__(self, pin, brightness=0.3, width=8, height=5): + self.pin=Pin(pin,Pin.OUT) + self.pin.value(1) + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_HMSB) + self.brightness = brightness + self._brightness = None + self.set_brightness(brightness) + time.sleep_ms(5) + self.fill(0) + self.show() + + def _write_cmd(self, val): + '''Serial write command''' + falg=0 + #Start bit + self.pin.value(1) + time.sleep_us(15) + self.pin.value(0) + time.sleep_us(30) + #Data bits + for i in range(8): + if (val >> i) & 0x01: + self.pin.value(1) + falg+=1 + else: + self.pin.value(0) + falg+=0 + time.sleep_us(44) + #Check bit + self.pin.value(1) if falg%2 == 0 else self.pin.value(0) + time.sleep_us(50) + #Stop bit + self.pin.value(1) + time.sleep_us(15) + + def get_brightness(self): + return round(self.brightness,2) + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0~1.0") + self.brightness = brightness + xbright = round(15 * brightness) + xbright = ((xbright & 0xA) >>1) | ((xbright & 0x5) <<1) + xbright = ((xbright & 0xC) >>2) | ((xbright & 0x3) <<2) + self._brightness = (xbright << 4) | _TM1652_SET_CUR #高四位倒序|驱动电流 + + def show(self): + """Refresh the display and show the changes.""" + for _ in range(2): + self._write_cmd(_TM1652_REG_ADD) + for i in range(5): + self._write_cmd(self._buffer[i]) + time.sleep_ms(3) + self._write_cmd(_TM1652_REG_CMD) + self._write_cmd(self._brightness) + time.sleep_ms(3) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/tm1680.py b/mixly/boards/default_src/micropython/origin/build/lib/tm1680.py new file mode 100644 index 00000000..ea078aad --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/tm1680.py @@ -0,0 +1,68 @@ +""" +TM1680 + +library for the TM1680 Matrix32x12 +======================================================= + +#Preliminary composition 20230412 + +@dahanzimin From the Mixly Team +""" +import uframebuf +from micropython import const + +TM1680_SYS_EN = const(0x81) +TM1680_LED_ON = const(0x83) +TM1680_COM_16N = const(0xA4) + +class TM1680(uframebuf.FrameBuffer_Uincode): + def __init__(self, i2c, address=0x72, brightness=0.3, width=32, height=12): + self._device= i2c + self._address = address + self._blink_rate=0 + self._brightness=brightness + self._buffer = bytearray((width + 7) // 8 * height) + super().__init__(self._buffer, width, height, uframebuf.MONO_HMSB) + self._write_cmd(TM1680_SYS_EN) #打开系统振荡器 + self._write_cmd(TM1680_LED_ON) #开启 LED 循环 + self._write_cmd(TM1680_COM_16N) #16COM Nmos + self.blink_rate(0) + self.set_brightness(brightness) + self.fill(0) + self.show() + + def _write_cmd(self, val): + '''I2C write command''' + self._device.writeto(self._address,val.to_bytes(1, 'little')) + + def blink_rate(self, rate=None): + if rate is None: + return self._blink_rate + if not 0 <= rate <= 3: + raise ValueError("Blink rate must be an integer in the range: 0-3") + rate = rate & 0x03 + self._blink_rate = rate + self._write_cmd(0x88 | rate) + + def get_brightness(self): + return self._brightness + + def set_brightness(self, brightness): + if not 0.0 <= brightness <= 1.0: + raise ValueError("Brightness must be a decimal number in the range: 0.0-1.0") + self._brightness = brightness + xbright = round(15 * brightness) + xbright = xbright & 0x0F + self._write_cmd(0xB0 | xbright) + + def show(self): + """Refresh the display and show the changes.""" + tm_buffer = bytearray(48) + for i in range(len(self._buffer)): + if i<24: #Convert the buffer content according to the address of tm1680 + tm_buffer[i]=self._buffer[i*2-1] if i%2 else self._buffer[i*2] + else: + tm_buffer[i]=self._buffer[(i-23)*2-1] if i%2 else self._buffer[(i-23)*2] + #Convert the high and low 4 bits of the address content + tm_buffer[i]= (tm_buffer[i]>>4) | (tm_buffer[i] <<4) + self._device.writeto_mem(self._address,0x00,tm_buffer) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/tm1931.py b/mixly/boards/default_src/micropython/origin/build/lib/tm1931.py new file mode 100644 index 00000000..e97b9704 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/tm1931.py @@ -0,0 +1,67 @@ +""" +TM1931- + +Micropython library for the TM1931 (18 channel IO port extension) +======================================================= + +#Preliminary composition 20220614 + +dahanzimin From the Mixly Team +""" + +import time +import framebuf +from machine import UART +from micropython import const + +_TM1931_ADDRESS = const(0x54) +_TM1931_REG_SSD = const(0x00) +_TM1931_REG_UPD = const(0x16) +_TM1931_REG_RST = const(0x17) + +class TM1931: + def __init__(self, i2c_bus, addr=_TM1931_ADDRESS): + self._i2c=i2c_bus + self._addr = addr + self._duty = bytearray(18) + self.reset() + + def _wreg(self, reg, val): + '''Write memory address''' + self._i2c.writeto_mem(self._addr,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg,nbytes=1): + '''Read memory address''' + return self._i2c.readfrom_mem(self._addr, reg, nbytes)[0] if nbytes<=1 else self._i2c.readfrom_mem(self._addr, reg, nbytes)[0:nbytes] + + def work(self,start=True): + """Start and open all output channels""" + self._wreg(_TM1931_REG_SSD,0x01& start) + start=0xff if start else 0 + for i in range(0x13,0x16,1): + self._wreg(i,start) + + def update(self): + """Load PWM register and LED control register data""" + self._wreg(_TM1931_REG_UPD,0xff) + + def reset(self): + """Reset all registers to default state""" + self._wreg(_TM1931_REG_RST,0x00) + self.work(True) + + def duty(self,index): + """Obtain PWM duty cycle""" + if not 1 <= index <= 18: + raise ValueError("Port must be a number in the range: 1-18") + return self._duty[index-1] + + def pwm(self,index,duty): + """18 channel PWM duty cycle data register""" + if not 0 <= duty <= 255: + raise ValueError("Duty must be a number in the range: 0-255") + if not 1 <= index <= 18: + raise ValueError("Port must be a number in the range: 1-18") + self._duty[index-1] = duty + self._wreg(index,duty) + self.update() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/tvoc07s.py b/mixly/boards/default_src/micropython/origin/build/lib/tvoc07s.py new file mode 100644 index 00000000..dd509b8b --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/tvoc07s.py @@ -0,0 +1,39 @@ +""" +TVOC + +Micropython library for the TVOC(UART) +======================================================= +@dahanzimin From the Mixly Team +""" +import time + +class TVOC: + def __init__(self, uart): + self._uart = uart + self._uart.init(baudrate=9600) + self._tvoc = (0, 0 ,0) #TVOC mg/m3, CH2O mg/m3, C02 ppm + self._flag = False + if not self._chip_id(): + raise AttributeError("Cannot find a TOVC") + + def _rreg(self): + '''Read data''' + if self._uart.any(): + eec = 0 + buf = self._uart.read(9) + for i in buf[:8]: + eec += i + if (eec & 0xFF) == buf[8] and buf[0] == 0x2C: + self._tvoc=((buf[2] << 8 | buf[3]) * 0.001, (buf[4] << 8 | buf[5]) * 0.001, buf[6] << 8 | buf[7] ) + return True + + def _chip_id(self): + for _ in range(5): + if self._rreg(): + return True + time.sleep(1) + return False + + def read(self): + self._rreg() + return self._tvoc diff --git a/mixly/boards/default_src/micropython/origin/build/lib/uart_com.py b/mixly/boards/default_src/micropython/origin/build/lib/uart_com.py new file mode 100644 index 00000000..aee88755 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/uart_com.py @@ -0,0 +1,27 @@ +""" +UART Communication + +MicroPython library for the UART_COM(Board to board communication) +======================================================= +#Preliminary composition 20220903 + +dahanzimin From the Mixly Team +""" +_sdata=None + +def send(uart,data,repeat=True): + global _sdata + if data != _sdata: + uart.write((str(data)+'\n')) + if not repeat: + _sdata=data + +def recv(uart): + data = uart.readline() + if data: + data_str = data.strip() + try: + data_str=data_str.decode() + return eval(data_str) + except: + return data_str diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ucs12071.py b/mixly/boards/default_src/micropython/origin/build/lib/ucs12071.py new file mode 100644 index 00000000..303b94ef --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ucs12071.py @@ -0,0 +1,78 @@ +""" +UCS12071 + +MicroPython library for the UCS12071 (Color sensor) +======================================================= +@dahanzimin From the Mixly Team +""" +import time +from micropython import const + +UCS_SYSM_CTRL = const(0x00) +UCS_INT_FLAG = const(0x02) +UCS_WAIT_TIME = const(0x03) +UCS_CLS_GAIN = const(0x04) +UCS_CLS_TIME = const(0x05) +UCS_CLS_DATA = const(0x1C) + +_GAINS_X = (1, 4, 8, 32, 96, 192) + +class UCS12071: + def __init__(self, i2c_bus, addr=0x38, gain=2): + self._device = i2c_bus + self._address = addr + self._gain = gain + self._color = [0, 0, 0] + self._ir = 0 + self._als = 0 + self._configure() + + def _wreg(self, reg, val): + '''Write memory address''' + self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little')) + + def _rreg(self, reg, nbytes=1): + '''Read memory address''' + return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes] + + def _configure(self): + '''Configuration Register''' + #self._wreg(UCS_SYSM_CTRL, 0x80) #Software reset + self._wreg(UCS_SYSM_CTRL, 0x03) #CLS & IR Enable + self._wreg(UCS_CLS_GAIN, 1 << self._gain | 0x80) #CLS sensing gain + self._wreg(UCS_CLS_TIME, 0x03) #CLSCONV INT_TIME + self._wreg(UCS_WAIT_TIME, 0x00) #10ms per time unit + + def status(self): + '''Data conversion status''' + return self._rreg(UCS_INT_FLAG) & 0x40 + + def getdata(self): + '''Processing data acquisition''' + if not self.status(): + _buf = self._rreg(UCS_CLS_DATA, 10) + self._color[0] = _buf[0] | _buf[1] << 8 + self._color[1] = _buf[2] | _buf[3] << 8 + self._color[2] = _buf[4] | _buf[5] << 8 + self._als = _buf[6] | _buf[7] << 8 + self._ir = _buf[8] | _buf[9] << 8 + return self._als, self._ir, self._color + + def color(self): + w, _, (r, g, b) = self.getdata() + if w == 0: + return (0, 0, 0) + else: + red = int(pow((int((r / w) * 256) / 255), 2.5) * 255) + green = int(pow((int((g / w) * 256) / 255), 2.5) * 255) + blue = int(pow((int((b / w) * 256) / 255), 2.5) * 255) + return (min(red, 255), min(green, 255), min(blue, 255)) + + def color_raw(self): + return self.getdata()[2] + + def ir(self): + return round(self.getdata()[1] / _GAINS_X[self._gain]) + + def als(self): + return round(self.getdata()[0] / _GAINS_X[self._gain]) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/uframebuf.py b/mixly/boards/default_src/micropython/origin/build/lib/uframebuf.py new file mode 100644 index 00000000..2dfa073e --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/uframebuf.py @@ -0,0 +1,573 @@ +""" +framebuf-extend + +Micropython library for the framebuf-extend +======================================================= +@dahanzimin From the Mixly Team +""" + +import esp, time, gc, math +from framebuf import * + +class Font_Ascall: + '''Ascall code font reading data''' + #字库格式:2字节字宽和高,后逐列式,按满字节低位在前 + font4x5_code=b'\x04\x05\x00\x00\x00\x00\x00\x17\x00\x00\x03\x00\x03\x00\x1f\n\x1f\x00\x16\x1f\x1a\x00\x19\x04\x13\x00\n\x15\x1a\x00\x00\x01\x03\x00\x00\x0e\x11\x00\x11\x0e\x00\x00\x15\x0e\x15\x00\x04\x0e\x04\x00\x00\x08\x18\x00\x04\x04\x04\x00\x18\x18\x00\x00\x18\x04\x03\x00\x1f\x11\x1f\x00\x12\x1f\x10\x00\x1d\x15\x17\x00\x15\x15\x1f\x00\x07\x04\x1f\x00\x17\x15\x1d\x00\x1f\x15\x1d\x00\x01\x01\x1f\x00\x1f\x15\x1f\x00\x17\x15\x1f\x00\x1b\x1b\x00\x00\x00\x0b\x1b\x00\x04\n\x11\x00\n\n\n\x00\x11\n\x04\x00\x01\x15\x07\x00\x0e\x15\x16\x00\x1e\x05\x1e\x00\x1f\x15\n\x00\x0e\x11\x11\x00\x1f\x11\x0e\x00\x1f\x15\x15\x00\x1f\x05\x05\x00\x0e\x15\x1d\x00\x1f\x04\x1f\x00\x11\x1f\x11\x00\x08\x11\x0f\x00\x1f\x0c\x12\x00\x1f\x10\x10\x00\x1f\x02\x1f\x00\x1e\x04\x0f\x00\x0e\x11\x0e\x00\x1f\x05\x02\x00\x0e\x19\x1e\x00\x1f\t\x16\x00\x12\x15\t\x00\x01\x1f\x01\x00\x1f\x10\x1f\x00\x0f\x10\x0f\x00\x1f\x08\x1f\x00\x1b\x04\x1b\x00\x07\x1c\x07\x00\x19\x15\x13\x00\x00\x1f\x11\x00\x03\x0c\x10\x00\x11\x1f\x00\x00\x02\x01\x02\x00\x10\x10\x10\x00\x00\x03\x02\x00\n\x16\x1e\x00\x1f\x14\x08\x00\x0c\x12\x12\x00\x08\x14\x1f\x00\x0c\x1a\x14\x00\x04\x1e\x05\x00\x14\x1a\x1e\x00\x1f\x04\x18\x00\x00\x1d\x00\x00\x10\x1d\x00\x00\x1e\x08\x14\x00\x00\x1e\x00\x00\x1e\x04\x1e\x00\x1e\x02\x1e\x00\x0c\x12\x0c\x00\x1e\n\x04\x00\x04\n\x1e\x00\x1e\x04\x02\x00\x12\x15\t\x00\x04\x1e\x14\x00\x1e\x10\x1e\x00\x0e\x10\x0e\x00\x1e\x08\x1e\x00\x12\x0c\x12\x00\x16\x18\x0e\x00\x19\x15\x13\x00\x04\x1f\x11\x00\x00\x1f\x00\x00\x11\x1f\x04\x00\x02\x06\x04\x00\x15\n\x15\x00' + font5x5_code=b'\x05\x05\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x03\x00\x03\x00\n\x1f\n\x1f\n\n\x17\x15\x1d\n\x13\t\x04\x12\x19\n\x15\x15\n\x10\x00\x03\x00\x00\x00\x00\x0e\x11\x00\x00\x00\x11\x0e\x00\x00\x00\n\x04\n\x00\x00\x04\x0e\x04\x00\x00\x10\x08\x00\x00\x00\x04\x04\x04\x00\x00\x08\x00\x00\x00\x10\x08\x04\x02\x01\x0e\x11\x11\x0e\x00\x00\x12\x1f\x10\x00\x19\x15\x15\x12\x00\t\x11\x15\x0b\x00\x0c\n\t\x1f\x08\x17\x15\x15\x15\t\x08\x14\x16\x15\x08\x11\t\x05\x03\x01\n\x15\x15\x15\n\x02\x15\r\x05\x02\x00\n\x00\x00\x00\x00\x10\n\x00\x00\x00\x04\n\x11\x00\x00\n\n\n\x00\x00\x11\n\x04\x00\x02\x01\x15\x05\x02\x0e\x11\x15\t\x0e\x1e\x05\x05\x1e\x00\x1f\x15\x15\n\x00\x0e\x11\x11\x11\x00\x1f\x11\x11\x0e\x00\x1f\x15\x15\x11\x00\x1f\x05\x05\x01\x00\x0e\x11\x11\x15\x0c\x1f\x04\x04\x1f\x00\x11\x1f\x11\x00\x00\t\x11\x11\x0f\x01\x1f\x04\n\x11\x00\x1f\x10\x10\x10\x00\x1f\x02\x04\x02\x1f\x1f\x02\x04\x08\x1f\x0e\x11\x11\x0e\x00\x1f\x05\x05\x02\x00\x06\t\x19\x16\x00\x1f\x05\x05\n\x10\x12\x15\x15\x08\x00\x01\x01\x1f\x01\x01\x0f\x10\x10\x0f\x00\x07\x08\x10\x08\x07\x07\x08\x10\x08\x07\x1b\x04\x04\x1b\x00\x01\x02\x1c\x02\x01\x19\x15\x13\x11\x00\x00\x1f\x11\x11\x00\x01\x02\x04\x08\x10\x00\x11\x11\x1f\x00\x00\x02\x01\x02\x00\x10\x10\x10\x10\x10\x00\x01\x02\x00\x00\x0c\x12\x12\x1e\x10\x1f\x14\x14\x08\x00\x0c\x12\x12\x12\x00\x08\x14\x14\x1f\x00\x0e\x15\x15\x12\x00\x04\x1e\x05\x01\x00\x02\x15\x15\x0f\x00\x1f\x04\x04\x18\x00\x00\x1d\x00\x00\x00\x00 \x1d\x00\x1f\x04\n\x10\x00\x00\x0f\x10\x10\x00\x1e\x02\x04\x02\x1e\x1e\x02\x02\x1c\x00\x0c\x12\x12\x0c\x00\x1e\n\n\x04\x00\x04\n\n\x1e\x00\x1c\x02\x02\x02\x00\x10\x14\n\x02\x00\x00\x0f\x14\x14\x10\x0e\x10\x10\x1e\x10\x06\x08\x10\x08\x06\x1e\x10\x08\x10\x1e\x12\x0c\x0c\x12\x00\x12\x14\x08\x04\x02\x12\x1a\x16\x12\x00\x00\x04\x1f\x11\x00\x00\x1f\x00\x00\x00\x11\x1f\x04\x00\x00\x00\x04\x04\x08\x08\x02\x06\x06\x06\x06' + font5x8_code=b'\x05\x08\x00\x00\x00\x00\x00\x00\x00_\x00\x00\x00\x07\x00\x07\x00\x14\x7f\x14\x7f\x14$*\x7f*\x12#\x13\x08db6IV P\x00\x08\x07\x03\x00\x00\x1c"A\x00\x00A"\x1c\x00*\x1c\x7f\x1c*\x08\x08>\x08\x08\x00\x80p0\x00\x08\x08\x08\x08\x08\x00\x00``\x00 \x10\x08\x04\x02>QIE>\x00B\x7f@\x00rIIIF!AIM3\x18\x14\x12\x7f\x10\'EEE9A]YN|\x12\x11\x12|\x7fIII6>AAA"\x7fAAA>\x7fIIIA\x7f\t\t\t\x01>AAQs\x7f\x08\x08\x08\x7f\x00A\x7fA\x00 @A?\x01\x7f\x08\x14"A\x7f@@@@\x7f\x02\x1c\x02\x7f\x7f\x04\x08\x10\x7f>AAA>\x7f\t\t\t\x06>AQ!^\x7f\t\x19)F&III2\x03\x01\x7f\x01\x03?@@@?\x1f @ \x1f?@8@?c\x14\x08\x14c\x03\x04x\x04\x03aYIMC\x00\x7fAAA\x02\x04\x08\x10 \x00AAA\x7f\x04\x02\x01\x02\x04@@@@@\x00\x03\x07\x08\x00 TTx@\x7f(DD88DDD(8DD(\x7f8TTT\x18\x00\x08~\t\x02\x18\xa4\xa4\x9cx\x7f\x08\x04\x04x\x00D}@\x00 @@=\x00\x7f\x10(D\x00\x00A\x7f@\x00|\x04x\x04x|\x08\x04\x04x8DDD8\xfc\x18$$\x18\x18$$\x18\xfc|\x08\x04\x04\x08HTTT$\x04\x04?D$<@@ |\x1c @ \x1c<@0@> 26 + buffer = bytearray(self.height*(font_width // 8 + 1)) + esp.flash_read(self.start_address + font_address, buffer) + return buffer, (font_width, self.height) + +class Image: + def load(self, path, invert=0): + self.invert = invert + with open(path, 'rb') as file: + image_type = file.read(2).decode() + file.seek(0) + img_arrays = bytearray(file.read()) + if image_type == 'P4': + buffer = self._pbm_decode(img_arrays) + elif image_type == 'BM': + buffer = self._bmp_decode(img_arrays) + else: + raise TypeError("Unsupported image format {}".format(image_type)) + gc.collect() + return buffer + + def load_py(self, name, invert=0): + self.invert = invert + image_type = name[0:2] + if image_type == b'P4': + buffer = self._pbm_decode(bytearray(name)) + elif image_type == b'BM': + buffer = self._bmp_decode(bytearray(name)) + else: + raise TypeError("Unsupported image format {}".format(image_type)) + gc.collect() + return buffer + + def _pbm_decode(self, img_arrays): + next_value = bytearray() + pnm_header = [] + stat = True + index = 3 + while stat: + next_byte = bytes([img_arrays[index]]) + if next_byte == b"#": + while bytes([img_arrays[index]]) not in [b"", b"\n"]: + index += 1 + if not next_byte.isdigit(): + if next_value: + pnm_header.append(int("".join(["%c" % char for char in next_value]))) + next_value = bytearray() + else: + next_value += next_byte + if len(pnm_header) == 2: + stat = False + index += 1 + pixel_arrays = img_arrays[index:] + if self.invert == 1: + for i in range(len(pixel_arrays)): + pixel_arrays[i] = (~pixel_arrays[i]) & 0xff + return pixel_arrays,(pnm_header[0], pnm_header[1]) + + def _bmp_decode(self, img_arrays): + file_size = int.from_bytes(img_arrays[2:6], 'little') + offset = int.from_bytes(img_arrays[10:14], 'little') + width = int.from_bytes(img_arrays[18:22], 'little') + height = int.from_bytes(img_arrays[22:26], 'little') + bpp = int.from_bytes(img_arrays[28:30], 'little') + if bpp != 1: + raise TypeError("Only support 1 bit color bmp") + line_bytes_size = (bpp * width + 31) // 32 * 4 + array_size = width * abs(height) // 8 + pixel_arrays = bytearray(array_size) + array_row = width // 8 + 1 if width % 8 else width // 8 + array_col = height + for i in range(array_col): + for j in range(array_row): + index = -(array_row * (i + 1) - j) + _offset = offset + i * line_bytes_size + j + if self.invert == 0: + pixel_byte = (~img_arrays[_offset]) & 0xff + else: + pixel_byte = img_arrays[_offset] + pixel_arrays[index] = pixel_byte + return pixel_arrays,(width, height) + +class FrameBuffer_Base(FrameBuffer): + """Inheritance and Extension""" + def __init__(self, buf, width, height, *args, **kw): + super().__init__(buf, width, height, *args, **kw) + self.width = width + self.height = height + self._buffer = buf + self._way = 1 + self._speed = 100 + self._miniqr = None + + def show(self): + print("External inheritance is required to override this method") + + def write(self): + self.show() + + def shift(self, x, y, rotate=False, sync=True): + """Shift pixels by x and y""" + if x > 0: # Shift Right + for _ in range(x): + for row in range(0, self.height): + last_pixel = super().pixel(self.width - 1, row) if rotate else 0 + for col in range(self.width - 1, 0, -1): + super().pixel(col, row, super().pixel(col - 1, row)) + super().pixel(0, row, last_pixel) + elif x < 0: # Shift Left + for _ in range(-x): + for row in range(0, self.height): + last_pixel = super().pixel(0, row) if rotate else 0 + for col in range(0, self.width - 1): + super().pixel(col, row, super().pixel(col + 1, row)) + super().pixel(self.width - 1, row, last_pixel) + if y > 0: # Shift Up + for _ in range(y): + for col in range(0, self.width): + last_pixel = super().pixel(col, self.height - 1) if rotate else 0 + for row in range(self.height - 1, 0, -1): + super().pixel(col, row, super().pixel(col, row - 1)) + super().pixel(col, 0, last_pixel) + elif y < 0: # Shift Down + for _ in range(-y): + for col in range(0, self.width): + last_pixel = super().pixel(col, 0) if rotate else 0 + for row in range(0, self.height - 1): + super().pixel(col, row, super().pixel(col, row + 1)) + super().pixel(col, self.height - 1, last_pixel) + if sync: self.show() + + def shift_right(self, num, rotate=False, sync=True): + """Shift all pixels right""" + self.shift(num, 0, rotate, sync) + + def shift_left(self, num, rotate=False, sync=True): + """Shift all pixels left""" + self.shift(-num, 0, rotate, sync) + + def shift_up(self, num, rotate=False, sync=True): + """Shift all pixels up""" + self.shift(0, -num, rotate, sync) + + def shift_down(self, num, rotate=False, sync=True): + """Shift all pixels down""" + self.shift(0, num, rotate, sync) + + def map_invert(self, own): + """Graph invert operation""" + if type(own) in [list, bytes, tuple, bytearray]: + result=bytearray() + for i in range(len(own)): + result.append(~ own[i]) + return result + else: + raise ValueError("This graphic operation is not supported") + + def map_add(self, own, other): + """Graph union operation""" + if type(own) in [list, bytes, tuple, bytearray] and type(other) in [list, bytes, tuple, bytearray]: + result=bytearray() + for i in range(min(len(own), len(other))): + result.append(own[i] | other[i]) + return result + else: + raise ValueError("This graphic operation is not supported") + + def map_sub(self, own, other): + """Graphic subtraction operation""" + if type(own) in [list, bytes, tuple, bytearray] and type(other) in [list, bytes, tuple, bytearray]: + result=bytearray() + for i in range(min(len(own), len(other))): + result.append((own[i] ^ other[i]) & own[i]) + return result + else: + raise ValueError("This graphic operation is not supported") + + def set_buffer(self, buffer, sync=True): + for i in range(min(len(buffer),len(self._buffer))): + self._buffer[i] = self._buffer[i] | buffer[i] + if sync: self.show() + + def get_buffer(self): + return self._buffer + + def pointern(self, x=None, y=None, l=None, angle=0, color=0xffff, bg_color=0x0, sync=True): + x = self.width // 2 if x is None else x + y = self.height // 2 if y is None else y + l = min(self.height // 2 , self.width // 2) if l is None else l + radian = math.radians(angle) + if sync: super().fill(bg_color) + super().line(x, y, round(x + l * math.sin(radian)), round(y - l * math.cos(radian)), color) + if sync: self.show() + + def pixel(self, x, y, color=None, sync=True): + if color is None: + return super().pixel(x, y) + else: + super().pixel(x, y, color) + if sync: self.show() + + def vline(self, x, y, h, c, sync=True): + super().vline(x, y, h, c) + if sync: self.show() + + def hline(self, x, y, w, c, sync=True): + super().hline(x, y, w, c) + if sync: self.show() + + def line(self, x1, y1, x2, y2, c, sync=True): + super().line(x1, y1, x2, y2, c) + if sync: self.show() + + def rect(self, x, y, w, h, c, sync=True): + super().rect(x, y, w, h, c) + if sync: self.show() + + def fill_rect(self, x, y, w, h, c, sync=True): + super().fill_rect(x, y, w, h, c) + if sync: self.show() + + def ellipse(self, x, y, xr, yr, c, f=False, sync=True): + super().ellipse(x, y, xr, yr, c, f) + if sync: self.show() + + def fill(self, c, sync=True): + super().fill(c) + if sync: self.show() + +class FrameBuffer_Ascall(FrameBuffer_Base): + '''FrameBuffer for Ascall''' + def font(self, font): + """Font selection or externally defined font code""" + self._font = Font_Ascall(font) + + def uin_font(self, font_address=0x3A0000): + """Uincode encoding font code""" + self._ufont = Font_Uincode(font_address) + + def scroll_way(self, way=1, speed=None): + """0,1竖,2,3横""" + self._way = way % 4 + if speed is not None: + self._speed = speed + + def bitmap(self, buffer, x=0, y=0): + """Graphic model display(buffer,(width,height))""" + buffer_info, (width, height) = buffer + if x < -width or x >= self.width or y < -height or y >= self.height: + return #Limit reasonable display area + for char_x in range(width): + for char_y in range(height): + if (buffer_info[char_x] >> char_y) & 0x1: + self.pixel(x + char_x, y + char_y, 1, sync=False) if height <= self.height else self.pixel(y + char_y, self.height - (x + char_x), 1, sync=False) + + def _uincode_scroll(self, buffer, space): + """Scroll to display uincode encoded characters""" + _len = 0 + for buf in buffer: + _len = _len + space + (buf[1][1] if self._way <= 1 else buf[1][0]) + for i in range(_len - space + (self.width if self._way <= 1 else self.height)): + _step = (self.width - 1 if self._way <= 1 else self.height) - i + self.fill(0, sync=False) + for buf in buffer: + _buf, (width, height) = buf + _xx = (self.width - width) // 2 + _yy = (self.width - height) // 2 + if -width < _step < self.width or -height < _step < self.height : + for _y in range(height): + for _x in range(width): + if _buf[_y * ((width + 7) // 8) + _x // 8] & (0x80 >> (_x & 7)): + if self._way == 0: + self.pixel(self.width - (_x + _xx) - 2, self.height - (_step + _y), 1, sync=False) + elif self._way == 1: + self.pixel(_xx + _x + 1, _step + _y, 1, sync=False) + elif self._way == 2: + self.pixel(_y +_yy, self.height - (_step + _x), 1, sync=False) + elif self._way == 3: + self.pixel(self.width - (_y +_yy) - 1, (_step + _x), 1, sync=False) + _step = _step + space + (height if self._way <= 1 else width) + self.show() + time.sleep_ms(self._speed) + + def _gb2312_scroll(self, data, space): + """Determine if the uincode is encoded""" + for char in data: + if ord(char) >= 0xFF: + font_buffer = [] + for c in data: + _buffer = self._ufont.chardata(c) + font_buffer.append(_buffer) + self._uincode_scroll(font_buffer, space) + return True + + def shows(self, data, space=0, center=True, sync=True): + """Display character""" + if data is not None: + self.fill(0, sync=False) + if type(data) in [list, bytes, tuple, bytearray]: + self.set_buffer(data, sync) + else: + data=str(data) + if not self._gb2312_scroll(data, space): + x = (self.width - len(data) * (self._font.font_width + space) + space) // 2 if center else 0 + for char in data: + self.bitmap(self._font.chardata(char), x) + x = self._font.font_width + x + space + if sync: self.show() + + def frame(self, data, delay=500): + """Display one frame per character""" + if data is not None: + if type(data) in [list,tuple]: + for dat in data: + if type(dat) in [list,bytes,tuple,bytearray]: + self.fill(0, sync=False) + self.set_buffer(data, True) + time.sleep_ms(delay) + else: + data=str(data) + for char in data: + self.fill(0, sync=False) + if ord(char) >= 0xFF: + _way = self._way + self._way = 1 + self._uincode_scroll([self._ufont.chardata(char)], 0) + self._way = _way + else: + self.bitmap(self._font.chardata(char), (self.width - self._font.font_width) // 2 ) + self.show() + time.sleep_ms(delay) + + def scroll(self, data, space=0, speed=None): + """Scrolling characters""" + if speed is not None: + self._speed = speed + if data is not None: + data = str(data) + if not self._gb2312_scroll(data, space): + str_len = len(data) * (self._font.font_width + space) - space + for i in range(str_len + self.width + 1): + x = -i + self.width + self.fill(0, sync=False) + for char in data: + self.bitmap(self._font.chardata(char),x) + x = self._font.font_width + x + space + self.show() + time.sleep_ms(self._speed) + +class FrameBuffer_Uincode(FrameBuffer_Base): + '''FrameBuffer for Uincode''' + def font(self, font_address=0x700000): + """Font selection or externally defined font code""" + self._font = Font_Uincode(font_address) + + def shift(self, x, y, rotate=False, sync=True): + '''Reshaping Inheritance Methods''' + super().scroll(x, y) + if sync: self.show() + + def image(self, path, x=None, y=None, size=None, invert=0, color=0xffff, bold=0, sync=True): + """Set buffer to value of Python Imaging Library image""" + if type(path) is str : + buffer_info, (width, height) = Image().load(path, invert) + elif type(path) in [bytes, bytearray]: + buffer_info, (width, height) = Image().load_py(path, invert) + else: + raise ValueError("invalid input") + if width > self.width or height > self.height: + raise ValueError("Image must be less than display ({0}x{1}).".format(self.width, self.height)) + size = min(self.height // height, self.width // width) if size is None else size + size = max(round(size), 1) + x =(self.width - width * size) // 2 if x is None else x + y =(self.height - height * size) // 2 if y is None else y + if sync: self.fill_rect(x, y, width * size, height * size, 0, sync=False) + self.bitmap((buffer_info,(width, height)), x, y, size, bold, color) + if sync: self.show() + + def bitmap(self, buffer, x=0, y=0, size=1, bold=0, color=0xffff): + """Graphic model display(buffer,(width,height))""" + buffer_info,(width,height)=buffer + if x < -width*size or x >= self.width or y < -height*size or y >= self.height: + return #Limit reasonable display area + bytewidth = (width + 7) // 8 + for j in range(height): + for i in range(width): + if buffer_info[j * bytewidth + i // 8] & (0x80 >> (i & 7)): + self.fill_rect(x + i * size, y + j * size, int(size + bold), int(size + bold), color, sync=False) + + def _take_buffer(self, strs, space, size=1): + '''Get character lattice information first''' + font_buffer = [] + font_len = 0 + for c in strs: + buffer = self._font.chardata(c) + font_buffer.append(buffer) + font_len = font_len + buffer[1][0] * size + space + return font_len, font_buffer + + def shows(self, data, space=0, center=True, x=0, y=None, size=None, color=0xffff, bold=0, bg_color=0x0, sync=True): + """Display character""" + if data is not None: + if type(data) in [list, bytes, tuple, bytearray]: + if sync: self.fill(bg_color, sync=False) + self.set_buffer(data, sync) + else: + yy = y + if size is None: + font_len, font_buffer = self._take_buffer(str(data), space, 1) + size = min((self.width // font_len) if font_len > 0 else 1, self.height // self._font.height) + size = max(round(size), 1) + font_len, font_buffer = self._take_buffer(str(data), space, size) + x = (self.width - font_len + space) // 2 if center else x + y = (self.height - self._font.height * size) // 2 if y is None else y + if sync: + if yy is None: + self.fill(bg_color, sync=False) + else: + self.fill_rect(0, y - 1, self.width, self._font.height * size + 2, bg_color, sync=False) + for buffer in font_buffer: #Display character + self.bitmap(buffer, x, y, size, bold, color) + x = buffer[1][0] * size + x + space + if sync: self.show() + + def texts(self, data, space_x=0, space_y=1, x=0, y=0, size=1, color=0xffff, bold=0, bg_color=0x0, sync=True): + size = max(round(size), 1) + lines = data.split('\n') + if sync: self.fill(bg_color, sync=False) + for line in lines: + for char in line: + buffer = self._font.chardata(char) + if x > self.width - buffer[1][0] * size: + x = 0 + y = buffer[1][1] * size + y + space_y + if y > self.height: + if sync: self.show() + return None + self.bitmap(buffer, x, y, size, bold, color) + x = buffer[1][0] * size + x + space_x + x = 0 + y = self._font.height * size + y + space_y + if sync: self.show() + + def frame(self, data, delay=500, size=None, color=0xffff, bold=0, bg_color=0x0): + """Display one frame per character""" + if data is not None: + if type(data) in [list, tuple]: + for dat in data: + if type(dat) in [list, bytes, tuple, bytearray]: + self.fill(bg_color, sync=False) + self.set_buffer(data, True) + time.sleep_ms(delay) + else: + size = self.height // (self._font.height * 3) if size is None else size + size = max(round(size), 1) + _, font_buffer = self._take_buffer(str(data), 0) + for buffer in font_buffer: + x=(self.width - buffer[1][0] * size) // 2 + y=(self.height - buffer[1][1] * size) // 2 + self.fill(bg_color, sync=False) + self.bitmap(buffer, x, y, size, bold, color) + self.show() + time.sleep_ms(delay) + + def scroll(self, data, space=0, speed=20, y=None, size=None, step= None, color=0xffff, bold=0, bg_color=0x0): + """Scrolling characters""" + if data is not None: + size = self.height // (self._font.height * 3) if size is None else size + size = max(round(size), 1) + step = max(self.width // 30, 1)if step is None else step + font_len, font_buffer = self._take_buffer(str(data), space, size) + for i in range(0, font_len - space + self.width, step): + x = -i + self.width + y = (self.height - self._font.height * size) // 2 if y is None else y + self.fill_rect(x - 2 , y - 2 , self.width -x + 4, font_buffer[0][1][1] * size + 4, bg_color, sync=False) + for buffer in font_buffer: + self.bitmap(buffer, x, y, size, bold, color) + x = buffer[1][0] * size + x + space + self.show() + time.sleep_ms(speed) + + def qrcode(self, data, x=None, y=None, size=None, bold=0, type=None, correct=0, color=0xffff, bg_color=0x0, sync=True): + if self._miniqr is None: + from adafruit_miniqr import QRCode + self._miniqr = QRCode + _qr = self._miniqr(qr_type=type, error_correct=correct) + _qr.add_data(str(data)) + _qr.make() + if sync: self.fill(bg_color, sync=False) + size = min(self.height // _qr.matrix.height, self.width // _qr.matrix.width) if size is None else size + x = (self.width - _qr.matrix.width * size) // 2 if x is None else x + y = (self.height - _qr.matrix.height * size) // 2 if y is None else y + for j in range(_qr.matrix.height): + for i in range(_qr.matrix.width): + if _qr.matrix[i, j]: + self.fill_rect(x + i * size, y + j * size, int(size + bold), int(size + bold), color, sync=False) + del _qr + gc.collect() + if sync: self.show() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/umqtt.py b/mixly/boards/default_src/micropython/origin/build/lib/umqtt.py new file mode 100644 index 00000000..21b781f6 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/umqtt.py @@ -0,0 +1,205 @@ +#Based on the traditional MQTT library +#@dahanzimin From the Mixly Team +import usocket as socket +import ustruct as struct + +# Add by Mixly Team +def str_len(object): + if isinstance(object, str): + return len(object.encode('utf-8')) + else: + return len(object) + +class MQTTException(Exception): + pass + +class MQTTClient: + def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,ssl=False, ssl_params={}): + if port == 0: + port = 8883 if ssl else 1883 + self.client_id = client_id + self.sock = socket.socket() + self.addr = socket.getaddrinfo(server, port)[0][-1] + self.ssl = ssl + self.ssl_params = ssl_params + self.pid = 0 + self.cb = None + self.user = user + self.pswd = password + self.keepalive = keepalive + self.lw_topic = None + self.lw_msg = None + self.lw_qos = 0 + self.lw_retain = False + + def _send_str(self, s): + self.sock.write(struct.pack("!H", str_len(s))) + self.sock.write(s) + + def _recv_len(self): + n = 0 + sh = 0 + while 1: + b = self.sock.read(1)[0] + n |= (b & 0x7f) << sh + if not b & 0x80: + return n + sh += 7 + + def set_callback(self, f): + self.cb = f + + def set_last_will(self, topic, msg, retain=False, qos=0): + assert 0 <= qos <= 2 + assert topic + self.lw_topic = topic + self.lw_msg = msg + self.lw_qos = qos + self.lw_retain = retain + + def connect(self, clean_session=True): + self.sock.connect(self.addr) + print(self.addr) + if self.ssl: + import ussl + self.sock = ussl.wrap_socket(self.sock, **self.ssl_params) + msg_header=bytearray([0x10]) + msg = bytearray(b"\x04MQTT\x04\x02\0\0") + msg_length = 12 + str_len(self.client_id) + msg[6] = clean_session << 1 + if self.user is not None: + msg_length += 2 + str_len(self.user) + 2 + str_len(self.pswd) + msg[6] |= 0xC0 + if self.keepalive: + assert self.keepalive < 65536 + msg[7] |= self.keepalive >> 8 + msg[8] |= self.keepalive & 0x00FF + if self.lw_topic: + msg_length += 2 + str_len(self.lw_topic) + 2 + str_len(self.lw_msg) + msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3 + msg[6] |= self.lw_retain << 5 + if msg_length > 0x7F: + while msg_length>0: + encoded_byte = msg_length % 0x80 + msg_length = msg_length // 0x80 + if msg_length > 0: + encoded_byte |= 0x80 + msg_header.append(encoded_byte) + msg_header.append(0x00) + else: + msg_header.append(msg_length) + msg_header.append(0x00) + self.sock.write(msg_header) + self.sock.write(msg) + + self._send_str(self.client_id) + if self.lw_topic: + self._send_str(self.lw_topic) + self._send_str(self.lw_msg) + if self.user is not None: + self._send_str(self.user) + self._send_str(self.pswd) + resp = self.sock.read(4) + assert resp[0] == 0x20 and resp[1] == 0x02 + if resp[3] != 0: + raise MQTTException(resp[3]) + return resp[2] & 1 + + def disconnect(self): + self.sock.write(b"\xe0\0") + self.sock.close() + + def ping(self): + self.sock.write(b"\xc0\0") + + def publish(self, topic, msg, retain=False, qos=0): + pkt = bytearray(b"\x30\0\0\0") + pkt[0] |= qos << 1 | retain + sz = 2 + str_len(topic) + str_len(msg) + if qos > 0: + sz += 2 + assert sz < 2097152 + i = 1 + while sz > 0x7f: + pkt[i] = (sz & 0x7f) | 0x80 + sz >>= 7 + i += 1 + pkt[i] = sz + self.sock.write(pkt, i + 1) + self._send_str(topic) + if qos > 0: + self.pid += 1 + pid = self.pid + struct.pack_into("!H", pkt, 0, pid) + self.sock.write(pkt, 2) + self.sock.write(msg) + if qos == 1: + while 1: + op = self.wait_msg() + if op == 0x40: + sz = self.sock.read(1) + assert sz == b"\x02" + rcv_pid = self.sock.read(2) + rcv_pid = rcv_pid[0] << 8 | rcv_pid[1] + if pid == rcv_pid: + return + elif qos == 2: + assert 0 + + def subscribe(self, topic, qos=0): + pkt = bytearray(b"\x82\0\0\0") + self.pid += 1 + struct.pack_into("!BH", pkt, 1, 2 + 2 + str_len(topic) + 1, self.pid) + self.sock.write(pkt) + self._send_str(topic) + self.sock.write(qos.to_bytes(1, "little")) + while 1: + op = self.wait_msg() + if op == 0x90: + resp = self.sock.read(4) + assert resp[1] == pkt[2] and resp[2] == pkt[3] + if resp[3] == 0x80: + raise MQTTException(resp[3]) + return + + # Wait for a single incoming MQTT message and process it. + def wait_msg(self): + res = self.sock.read(1) + self.sock.setblocking(True) + if res is None: + return None + if res == b"": + raise OSError(-1) + if res == b"\xd0": # PINGRESP + sz = self.sock.read(1)[0] + assert sz == 0 + return None + op = res[0] + if op & 0xf0 != 0x30: + return op + sz = self._recv_len() + topic_len = self.sock.read(2) + topic_len = (topic_len[0] << 8) | topic_len[1] + topic = self.sock.read(topic_len).decode('utf-8') + sz -= topic_len + 2 + if op & 6: + pid = self.sock.read(2) + pid = pid[0] << 8 | pid[1] + sz -= 2 + msg = self.sock.read(sz).decode('utf-8') + if op & 6 == 2: + pkt = bytearray(b"\x40\x02\0\0") + struct.pack_into("!H", pkt, 2, pid) + self.sock.write(pkt) + elif op & 6 == 4: + assert 0 + + if self.cb is None: + return {"msg":msg, "topic":topic} + else: + self.cb(topic, msg) + + # Checks whether a pending message from server is available. + def check_msg(self): + self.sock.setblocking(False) + return self.wait_msg() diff --git a/mixly/boards/default_src/micropython/origin/build/lib/urequests.py b/mixly/boards/default_src/micropython/origin/build/lib/urequests.py new file mode 100644 index 00000000..00c013f1 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/urequests.py @@ -0,0 +1,151 @@ +import usocket + +class Response: + + def __init__(self, f): + self.raw = f + self.encoding = "utf-8" + self._cached = None + + def close(self): + if self.raw: + self.raw.close() + self.raw = None + self._cached = None + + @property + def content(self): + if self._cached is None: + try: + self._cached = self.raw.read() + finally: + self.raw.close() + self.raw = None + return self._cached + + @property + def text(self): + return str(self.content, self.encoding) + + def json(self): + import ujson + return ujson.loads(self.content) + + +def request(method, url, data=None, json=None, headers={}, stream=None, parse_headers=True): + redir_cnt = 1 + while True: + try: + proto, dummy, host, path = url.split("/", 3) + except ValueError: + proto, dummy, host = url.split("/", 2) + path = "" + if proto == "http:": + port = 80 + elif proto == "https:": + import ssl + port = 443 + else: + raise ValueError("Unsupported protocol: " + proto) + + if ":" in host: + host, port = host.split(":", 1) + port = int(port) + + ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM) + ai = ai[0] + + resp_d = None + if parse_headers is not False: + resp_d = {} + + s = usocket.socket(ai[0], ai[1], ai[2]) + try: + s.connect(ai[-1]) + if proto == "https:": + s = ssl.wrap_socket(s, server_hostname=host) + s.write(b"%s /%s HTTP/1.0\r\n" % (method, path)) + if not "Host" in headers: + s.write(b"Host: %s\r\n" % host) + # Iterate over keys to avoid tuple alloc + for k in headers: + s.write(k) + s.write(b": ") + s.write(headers[k]) + s.write(b"\r\n") + if json is not None: + assert data is None + import ujson + data = ujson.dumps(json) + s.write(b"Content-Type: application/json\r\n") + if data: + s.write(b"Content-Length: %d\r\n" % len(data)) + s.write(b"Connection: close\r\n\r\n") + if data: + s.write(data) + + l = s.readline() + #print(l) + l = l.split(None, 2) + status = int(l[1]) + reason = "" + if len(l) > 2: + reason = l[2].rstrip() + while True: + l = s.readline() + if not l or l == b"\r\n": + break + #print(l) + + if l.startswith(b"Transfer-Encoding:"): + if b"chunked" in l: + raise ValueError("Unsupported " + l) + elif l.startswith(b"Location:") and 300 <= status <= 399: + if not redir_cnt: + raise ValueError("Too many redirects") + redir_cnt -= 1 + url = l[9:].decode().strip() + #print("redir to:", url) + status = 300 + break + + if parse_headers is False: + pass + elif parse_headers is True: + l = l.decode() + k, v = l.split(":", 1) + resp_d[k] = v.strip() + else: + parse_headers(l, resp_d) + except OSError: + s.close() + raise + + if status != 300: + break + + resp = Response(s) + resp.status_code = status + resp.reason = reason + if resp_d is not None: + resp.headers = resp_d + return resp + + +def head(url, **kw): + return request("HEAD", url, **kw) + +def get(url, **kw): + return request("GET", url, **kw) + +def post(url, **kw): + return request("POST", url, **kw) + +def put(url, **kw): + return request("PUT", url, **kw) + +def patch(url, **kw): + return request("PATCH", url, **kw) + +def delete(url, **kw): + return request("DELETE", url, **kw) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/urllib.py b/mixly/boards/default_src/micropython/origin/build/lib/urllib.py new file mode 100644 index 00000000..a02329fe --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/urllib.py @@ -0,0 +1,32 @@ +from ucollections import namedtuple + +URI = namedtuple('URI', ('cheme', 'netloc', 'path', 'params', 'query', 'fragment')) + +def quote(string, safe='_.-~+'): + """ A simple implementation of URL quoting""" + string = string.replace(' ', '+') + result = "" + for char in string: + if ('a' <= char <= 'z') or ('A' <= char <= 'Z') or ('0' <= char<= '9') or (char in safe): + result += char + else: + result += "%{:02X}".format(ord(char)) + return result + +def urlencode(query, safe='_.-~+'): + """A simple urlencode function""" + return '&'.join('{}={}'.format(quote(k, safe), quote(v, safe)) for k, v in query.items()) + +def urlparse(url): + """A simple urlparse (cheme, netloc, path, params, query, fragment)""" + parts = [''] * 6 + for i, sep in enumerate(['://', '#', '?', ';']): + if sep in url: + left, right = url.split(sep, 1) + parts[i], url = left, right + if '/' in url: + parts[1], parts[2] = url.split('/', 1) + parts[2] = '/' + parts[2] + else: + parts[1] = url + return URI(*parts) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/urllib_parse.py b/mixly/boards/default_src/micropython/origin/build/lib/urllib_parse.py new file mode 100644 index 00000000..b3ffaf0d --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/urllib_parse.py @@ -0,0 +1,187 @@ +# Characters valid in scheme names +scheme_chars = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789" "+-." + +# XXX: Consider replacing with functools.lru_cache +MAX_CACHE_SIZE = 20 + +_ALWAYS_SAFE = frozenset(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ" b"abcdefghijklmnopqrstuvwxyz" b"0123456789" b"_.-") +_ALWAYS_SAFE_BYTES = bytes(_ALWAYS_SAFE) +_safe_quoters = {} + + +def clear_cache(): + """Clear the parse cache and the quoters cache.""" + _safe_quoters.clear() + + +_hexdig = "0123456789ABCDEFabcdef" +_hextobyte = {(a + b).encode(): bytes([int(a + b, 16)]) for a in _hexdig for b in _hexdig} + + +def unquote_to_bytes(string): + """unquote_to_bytes('abc%20def') -> b'abc def'.""" + # Note: strings are encoded as UTF-8. This is only an issue if it contains + # unescaped non-ASCII characters, which URIs should not. + if not string: + # Is it a string-like object? + string.split + return b"" + if isinstance(string, str): + string = string.encode("utf-8") + bits = string.split(b"%") + if len(bits) == 1: + return string + res = [bits[0]] + append = res.append + for item in bits[1:]: + try: + append(_hextobyte[item[:2]]) + append(item[2:]) + except KeyError: + append(b"%") + append(item) + return b"".join(res) + + +def split_on_non_ascii(s): + """ + Splits the input string wherever a character is not ASCII (ord(c) not in 0..127). + Returns a list of substrings and the non-ASCII characters as separate elements. + """ + result = [] + current = [] + for c in s: + if 0 <= ord(c) <= 127: + current.append(c) + else: + if current: + result.append("".join(current)) + current = [] + result.append(c) + if current: + result.append("".join(current)) + return result + + +def unquote(string, encoding="utf-8", errors="replace"): + """Replace %xx escapes by their single-character equivalent. The optional + encoding and errors parameters specify how to decode percent-encoded + sequences into Unicode characters, as accepted by the bytes.decode() + method. + By default, percent-encoded sequences are decoded with UTF-8, and invalid + sequences are replaced by a placeholder character. + + unquote('abc%20def') -> 'abc def'. + """ + if "%" not in string: + string.split + return string + if encoding is None: + encoding = "utf-8" + if errors is None: + errors = "replace" + bits = split_on_non_ascii(string) + res = [] + append = res.append + for i in range(0, len(bits), 2): + append(unquote_to_bytes(bits[i]).decode(encoding, errors)) + if i + 1 < len(bits): + # Append the non-ASCII part as is + append(bits[i + 1]) + return "".join(res) + + +class Quoter: + """A mapping from bytes (in range(0,256)) to strings. + + String values are percent-encoded byte values, unless the key < 128, and + in the "safe" set (either the specified safe set, or default set). + """ + + # Keeps a cache internally, using defaultdict, for efficiency (lookups + # of cached keys don't call Python code at all). + def __init__(self, safe): + """safe: bytes object.""" + self.safe = _ALWAYS_SAFE.union(safe) + self.cache = {} + + def get(self, b): + try: + return self.cache[b] + except KeyError: + # Handle a cache miss. Store quoted string in cache and return. + res = chr(b) if b in self.safe else "%{:02X}".format(b) + self.cache[b] = res + return res + + +def quote(string, safe="/", encoding=None, errors=None): + """quote('abc def') -> 'abc%20def' + + Each part of a URL, e.g. the path info, the query, etc., has a + different set of reserved characters that must be quoted. + + RFC 2396 Uniform Resource Identifiers (URI): Generic Syntax lists + the following reserved characters. + + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + "$" | "," + + Each of these characters is reserved in some component of a URL, + but not necessarily in all of them. + + By default, the quote function is intended for quoting the path + section of a URL. Thus, it will not encode '/'. This character + is reserved, but in typical usage the quote function is being + called on a path where the existing slash characters are used as + reserved characters. + + string and safe may be either str or bytes objects. encoding must + not be specified if string is a str. + + The optional encoding and errors parameters specify how to deal with + non-ASCII characters, as accepted by the str.encode method. + By default, encoding='utf-8' (characters are encoded with UTF-8), and + errors='strict' (unsupported characters raise a UnicodeEncodeError). + """ + if isinstance(string, str): + if not string: + return string + if encoding is None: + encoding = "utf-8" + if errors is None: + errors = "strict" + string = string.encode(encoding, errors) + else: + if encoding is not None: + raise TypeError("quote() doesn't support 'encoding' for bytes") + if errors is not None: + raise TypeError("quote() doesn't support 'errors' for bytes") + return quote_from_bytes(string, safe) + + +def quote_from_bytes(bs, safe="/"): + """Like quote(), but accepts a bytes object rather than a str, and does + not perform string-to-bytes encoding. It always returns an ASCII string. + quote_from_bytes(b'abc def\x3f') -> 'abc%20def%3f' + """ + if not isinstance(bs, (bytes, bytearray)): + raise TypeError("quote_from_bytes() expected bytes") + if not bs: + return "" + if isinstance(safe, str): + # Normalize 'safe' by converting to bytes and removing non-ASCII chars + safe = safe.encode("ascii", "ignore") + else: + safe = bytes([c for c in safe if c < 128]) + if not bs.rstrip(_ALWAYS_SAFE_BYTES + safe): + return bs.decode() + try: + quoter = _safe_quoters[safe] + except KeyError as e: + _safe_quoters[safe] = quoter = Quoter(safe) + + res = "" + for char in bs: + res += quoter.get(char) + return res \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/vl53l0x.py b/mixly/boards/default_src/micropython/origin/build/lib/vl53l0x.py new file mode 100644 index 00000000..093fba47 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/vl53l0x.py @@ -0,0 +1,350 @@ +""" +VL53L0X + +Micropython library for the VL53L0X +======================================================= + +#https://github.com/mcauser/deshipu-micropython-vl53l0x.git 20220216 + +dahanzimin From the Mixly Team +""" +from micropython import const +import ustruct +import utime + + +_IO_TIMEOUT = 1000 +_SYSRANGE_START = const(0x00) +_EXTSUP_HV = const(0x89) +_MSRC_CONFIG = const(0x60) +_FINAL_RATE_RTN_LIMIT = const(0x44) +_SYSTEM_SEQUENCE = const(0x01) +_SPAD_REF_START = const(0x4f) +_SPAD_ENABLES = const(0xb0) +_REF_EN_START_SELECT = const(0xb6) +_SPAD_NUM_REQUESTED = const(0x4e) +_INTERRUPT_GPIO = const(0x0a) +_INTERRUPT_CLEAR = const(0x0b) +_GPIO_MUX_ACTIVE_HIGH = const(0x84) +_RESULT_INTERRUPT_STATUS = const(0x13) +_RESULT_RANGE_STATUS = const(0x14) +_OSC_CALIBRATE = const(0xf8) +_MEASURE_PERIOD = const(0x04) + + +class TimeoutError(RuntimeError): + pass + + +class VL53L0X: + def __init__(self, i2c, address=0x29): + self.i2c = i2c + self.address = address + self.init() + self._started = False + + def _registers(self, register, values=None, struct='B'): + if values is None: + size = ustruct.calcsize(struct) + data = self.i2c.readfrom_mem(self.address, register, size) + values = ustruct.unpack(struct, data) + return values + data = ustruct.pack(struct, *values) + self.i2c.writeto_mem(self.address, register, data) + + def _register(self, register, value=None, struct='B'): + if value is None: + return self._registers(register, struct=struct)[0] + self._registers(register, (value,), struct=struct) + + def _flag(self, register=0x00, bit=0, value=None): + data = self._register(register) + mask = 1 << bit + if value is None: + return bool(data & mask) + elif value: + data |= mask + else: + data &= ~mask + self._register(register, data) + + def _config(self, *config): + for register, value in config: + self._register(register, value) + + def init(self, power2v8=True): + self._flag(_EXTSUP_HV, 0, power2v8) + + # I2C standard mode + self._config( + (0x88, 0x00), + + (0x80, 0x01), + (0xff, 0x01), + (0x00, 0x00), + ) + self._stop_variable = self._register(0x91) + self._config( + (0x00, 0x01), + (0xff, 0x00), + (0x80, 0x00), + ) + + # disable signal_rate_msrc and signal_rate_pre_range limit checks + self._flag(_MSRC_CONFIG, 1, True) + self._flag(_MSRC_CONFIG, 4, True) + + # rate_limit = 0.25 + self._register(_FINAL_RATE_RTN_LIMIT, int(0.25 * (1 << 7)), + struct='>H') + + self._register(_SYSTEM_SEQUENCE, 0xff) + + spad_count, is_aperture = self._spad_info() + spad_map = bytearray(self._registers(_SPAD_ENABLES, struct='6B')) + + # set reference spads + self._config( + (0xff, 0x01), + (_SPAD_REF_START, 0x00), + (_SPAD_NUM_REQUESTED, 0x2c), + (0xff, 0x00), + (_REF_EN_START_SELECT, 0xb4), + ) + + spads_enabled = 0 + for i in range(48): + if i < 12 and is_aperture or spads_enabled >= spad_count: + spad_map[i // 8] &= ~(1 << (i >> 2)) + elif spad_map[i // 8] & (1 << (i >> 2)): + spads_enabled += 1 + + self._registers(_SPAD_ENABLES, spad_map, struct='6B') + + self._config( + (0xff, 0x01), + (0x00, 0x00), + + (0xff, 0x00), + (0x09, 0x00), + (0x10, 0x00), + (0x11, 0x00), + + (0x24, 0x01), + (0x25, 0xFF), + (0x75, 0x00), + + (0xFF, 0x01), + (0x4E, 0x2C), + (0x48, 0x00), + (0x30, 0x20), + + (0xFF, 0x00), + (0x30, 0x09), + (0x54, 0x00), + (0x31, 0x04), + (0x32, 0x03), + (0x40, 0x83), + (0x46, 0x25), + (0x60, 0x00), + (0x27, 0x00), + (0x50, 0x06), + (0x51, 0x00), + (0x52, 0x96), + (0x56, 0x08), + (0x57, 0x30), + (0x61, 0x00), + (0x62, 0x00), + (0x64, 0x00), + (0x65, 0x00), + (0x66, 0xA0), + + (0xFF, 0x01), + (0x22, 0x32), + (0x47, 0x14), + (0x49, 0xFF), + (0x4A, 0x00), + + (0xFF, 0x00), + (0x7A, 0x0A), + (0x7B, 0x00), + (0x78, 0x21), + + (0xFF, 0x01), + (0x23, 0x34), + (0x42, 0x00), + (0x44, 0xFF), + (0x45, 0x26), + (0x46, 0x05), + (0x40, 0x40), + (0x0E, 0x06), + (0x20, 0x1A), + (0x43, 0x40), + + (0xFF, 0x00), + (0x34, 0x03), + (0x35, 0x44), + + (0xFF, 0x01), + (0x31, 0x04), + (0x4B, 0x09), + (0x4C, 0x05), + (0x4D, 0x04), + + (0xFF, 0x00), + (0x44, 0x00), + (0x45, 0x20), + (0x47, 0x08), + (0x48, 0x28), + (0x67, 0x00), + (0x70, 0x04), + (0x71, 0x01), + (0x72, 0xFE), + (0x76, 0x00), + (0x77, 0x00), + + (0xFF, 0x01), + (0x0D, 0x01), + + (0xFF, 0x00), + (0x80, 0x01), + (0x01, 0xF8), + + (0xFF, 0x01), + (0x8E, 0x01), + (0x00, 0x01), + (0xFF, 0x00), + (0x80, 0x00), + ) + + self._register(_INTERRUPT_GPIO, 0x04) + self._flag(_GPIO_MUX_ACTIVE_HIGH, 4, False) + self._register(_INTERRUPT_CLEAR, 0x01) + + # XXX Need to implement this. + #budget = self._timing_budget() + #self._register(_SYSTEM_SEQUENCE, 0xe8) + #self._timing_budget(budget) + + self._register(_SYSTEM_SEQUENCE, 0x01) + self._calibrate(0x40) + self._register(_SYSTEM_SEQUENCE, 0x02) + self._calibrate(0x00) + + self._register(_SYSTEM_SEQUENCE, 0xe8) + + def _spad_info(self): + self._config( + (0x80, 0x01), + (0xff, 0x01), + (0x00, 0x00), + + (0xff, 0x06), + ) + self._flag(0x83, 3, True) + self._config( + (0xff, 0x07), + (0x81, 0x01), + + (0x80, 0x01), + + (0x94, 0x6b), + (0x83, 0x00), + ) + for timeout in range(_IO_TIMEOUT): + if self._register(0x83): + break + utime.sleep_ms(1) + else: + raise TimeoutError() + self._config( + (0x83, 0x01), + ) + value = self._register(0x92) + self._config( + (0x81, 0x00), + (0xff, 0x06), + ) + self._flag(0x83, 3, False) + self._config( + (0xff, 0x01), + (0x00, 0x01), + + (0xff, 0x00), + (0x80, 0x00), + ) + count = value & 0x7f + is_aperture = bool(value & 0b10000000) + return count, is_aperture + + def _calibrate(self, vhv_init_byte): + self._register(_SYSRANGE_START, 0x01 | vhv_init_byte) + for timeout in range(_IO_TIMEOUT): + if self._register(_RESULT_INTERRUPT_STATUS) & 0x07: + break + utime.sleep_ms(1) + else: + raise TimeoutError() + self._register(_INTERRUPT_CLEAR, 0x01) + self._register(_SYSRANGE_START, 0x00) + + def start(self, period=0): + self._config( + (0x80, 0x01), + (0xFF, 0x01), + (0x00, 0x00), + (0x91, self._stop_variable), + (0x00, 0x01), + (0xFF, 0x00), + (0x80, 0x00), + ) + if period: + oscilator = self._register(_OSC_CALIBRATE, struct='>H') + if oscilator: + period *= oscilator + self._register(_MEASURE_PERIOD, period, struct='>H') + self._register(_SYSRANGE_START, 0x04) + else: + self._register(_SYSRANGE_START, 0x02) + self._started = True + + def stop(self): + self._register(_SYSRANGE_START, 0x01) + self._config( + (0xFF, 0x01), + (0x00, 0x00), + (0x91, self._stop_variable), + (0x00, 0x01), + (0xFF, 0x00), + ) + self._started = False + + def read(self): + if not self._started: + self._config( + (0x80, 0x01), + (0xFF, 0x01), + (0x00, 0x00), + (0x91, self._stop_variable), + (0x00, 0x01), + (0xFF, 0x00), + (0x80, 0x00), + (_SYSRANGE_START, 0x01), + ) + for timeout in range(_IO_TIMEOUT): + if not self._register(_SYSRANGE_START) & 0x01: + break + utime.sleep_ms(1) + else: + raise TimeoutError() + for timeout in range(_IO_TIMEOUT): + if self._register(_RESULT_INTERRUPT_STATUS) & 0x07: + break + utime.sleep_ms(1) + else: + raise TimeoutError() + value = self._register(_RESULT_RANGE_STATUS + 10, struct='>H') + self._register(_INTERRUPT_CLEAR, 0x01) + return value + + diff --git a/mixly/boards/default_src/micropython/origin/build/lib/websocket.py b/mixly/boards/default_src/micropython/origin/build/lib/websocket.py new file mode 100644 index 00000000..2d79c367 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/websocket.py @@ -0,0 +1,229 @@ +'''''' +import usocket as socket +import ubinascii as binascii +import urandom as random +import ustruct as struct +import urandom as random +from ucollections import namedtuple + +# Opcodes +OP_CONT = const(0x0) +OP_TEXT = const(0x1) +OP_BYTES = const(0x2) +OP_CLOSE = const(0x8) +OP_PING = const(0x9) +OP_PONG = const(0xA) + +# Close codes +CLOSE_OK = const(1000) +CLOSE_GOING_AWAY = const(1001) +CLOSE_PROTOCOL_ERROR = const(1002) +CLOSE_DATA_NOT_SUPPORTED = const(1003) +CLOSE_BAD_DATA = const(1007) +CLOSE_POLICY_VIOLATION = const(1008) +CLOSE_TOO_BIG = const(1009) +CLOSE_MISSING_EXTN = const(1010) +CLOSE_BAD_CONDITION = const(1011) + +URI = namedtuple('URI', ('protocol', 'hostname', 'port', 'path')) + +class NoDataException(Exception): + pass + +class ConnectionClosed(Exception): + pass + +def urlparse(uri): + # Split protocol and the rest + protocol, rest = uri.split('://', 1) + if '/' in rest: + hostname_port, path = rest.split('/', 1) + path = '/' + path + else: + hostname_port, path = rest, '' + if ':' in hostname_port: + hostname, port = hostname_port.rsplit(':', 1) + else: + hostname, port = hostname_port, None + if port is None: + port = 443 if protocol == 'wss' else 80 + return URI(protocol, hostname, port, path) + +class Websocket: + """Basis of the Websocket protocol.""" + + is_client = False + + def __init__(self, sock): + self.sock = sock + self.open = True + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + self.close() + + def settimeout(self, timeout): + self.sock.settimeout(timeout) + + def read_frame(self, max_size=None): + """Read a frame from the socket""" + # Frame header + two_bytes = self.sock.read(2) + if not two_bytes: + raise NoDataException + byte1, byte2 = struct.unpack('!BB', two_bytes) + # Byte 1: FIN(1) _(1) _(1) _(1) OPCODE(4) + fin = bool(byte1 & 0x80) + opcode = byte1 & 0x0F + # Byte 2: MASK(1) LENGTH(7) + mask = bool(byte2 & (1 << 7)) + length = byte2 & 0x7F + + if length == 126: # Magic number, length header is 2 bytes + (length,) = struct.unpack('!H', self.sock.read(2)) + elif length == 127: # Magic number, length header is 8 bytes + (length,) = struct.unpack('!Q', self.sock.read(8)) + if mask: # Mask is 4 bytes + mask_bits = self.sock.read(4) + try: + data = self.sock.read(length) + except MemoryError: + # We can't receive this many bytes, close the socket + self.close(code=CLOSE_TOO_BIG) + return True, OP_CLOSE, None + if mask: + data = bytes(b ^ mask_bits[i % 4] for i, b in enumerate(data)) + return fin, opcode, data + + def write_frame(self, opcode, data=b''): + """Write a frame to the socket""" + fin = True + mask = self.is_client # messages sent by client are masked + + length = len(data) + # Frame header + # Byte 1: FIN(1) _(1) _(1) _(1) OPCODE(4) + byte1 = 0x80 if fin else 0 + byte1 |= opcode + # Byte 2: MASK(1) LENGTH(7) + byte2 = 0x80 if mask else 0 + if length < 126: # 126 is magic value to use 2-byte length header + byte2 |= length + self.sock.write(struct.pack('!BB', byte1, byte2)) + elif length < (1 << 16): # Length fits in 2-bytes + byte2 |= 126 # Magic code + self.sock.write(struct.pack('!BBH', byte1, byte2, length)) + elif length < (1 << 64): + byte2 |= 127 # Magic code + self.sock.write(struct.pack('!BBQ', byte1, byte2, length)) + else: + raise ValueError() + if mask: # Mask is 4 bytes + mask_bits = struct.pack('!I', random.getrandbits(32)) + self.sock.write(mask_bits) + data = bytes(b ^ mask_bits[i % 4] for i, b in enumerate(data)) + self.sock.write(data) + + def recv(self): + """Receive data from the websocket""" + assert self.open + + while self.open: + try: + fin, opcode, data = self.read_frame() + except NoDataException: + return '' + except ValueError: + self._close() + raise ConnectionClosed() + + if not fin: + raise NotImplementedError() + + if opcode == OP_TEXT: + return data.decode('utf-8') + elif opcode == OP_BYTES: + return data + elif opcode == OP_CLOSE: + self._close() + return + elif opcode == OP_PONG: + # Ignore this frame, keep waiting for a data frame + continue + elif opcode == OP_PING: + # We need to send a pong frame + self.write_frame(OP_PONG, data) + # And then wait to receive + continue + elif opcode == OP_CONT: + # This is a continuation of a previous frame + raise NotImplementedError(opcode) + else: + raise ValueError(opcode) + + def send(self, buf): + """Send data to the websocket.""" + assert self.open + if isinstance(buf, str): + opcode = OP_TEXT + buf = buf.encode('utf-8') + elif isinstance(buf, bytes): + opcode = OP_BYTES + else: + raise TypeError() + self.write_frame(opcode, buf) + + def close(self, code=CLOSE_OK, reason=''): + """Close the websocket.""" + if not self.open: + return + buf = struct.pack('!H', code) + reason.encode('utf-8') + self.write_frame(OP_CLOSE, buf) + self._close() + + def _close(self): + self.open = False + self.sock.close() + +class WebsocketClient(Websocket): + is_client = True + +def connect(uri, headers=None): + """Connect a websocket.""" + uri = urlparse(uri) + assert uri + sock = socket.socket() + addr = socket.getaddrinfo(uri.hostname, uri.port) + sock.connect(addr[0][4]) + if uri.protocol == 'wss': + import ssl as ussl + sock = ussl.wrap_socket(sock, server_hostname=uri.hostname) + + def send_header(header, *args): + sock.write(header % args + '\r\n') + + # Sec-WebSocket-Key is 16 bytes of random base64 encoded + key = binascii.b2a_base64(bytes(random.getrandbits(8) for _ in range(16)))[:-1] + + send_header(b'GET %s HTTP/1.1', uri.path or '/') + send_header(b'Host: %s:%s', uri.hostname, uri.port) + send_header(b'Connection: Upgrade') + send_header(b'Upgrade: websocket') + send_header(b'Sec-WebSocket-Key: %s', key) + send_header(b'Sec-WebSocket-Version: 13') + send_header(b'Origin: http://{hostname}:{port}'.format(hostname=uri.hostname, port=uri.port)) + if headers: # 注入自定义头 + for k, v in headers.items(): + send_header((k + ": " + v).encode()) + send_header(b'') + + header = sock.readline()[:-2] + assert header.startswith(b'HTTP/1.1 101 '), header + # We don't (currently) need these headers + # FIXME: should we check the return key? + while header: + header = sock.readline()[:-2] + + return WebsocketClient(sock) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ws2812.py b/mixly/boards/default_src/micropython/origin/build/lib/ws2812.py new file mode 100644 index 00000000..abe6e783 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ws2812.py @@ -0,0 +1,84 @@ +""" +WS2812 RGB + +Micropython library for the WS2812 NeoPixel-RGB +======================================================= + +#Preliminary composition 20240110 + +dahanzimin From the Mixly Team +""" +from time import sleep +from machine import bitstream + +class NeoPixel: + def __init__(self, pin, n, bpp=3, timing=1, ORDER=(1, 0, 2, 3), default=None, multiplex=False, leds=0): + self.pin = pin + self.bpp = bpp + self.leds = leds + self.rgbs = n-leds + self.ORDER = ORDER + self.multiplex = multiplex + self.rgb_buf = bytearray(self.rgbs * bpp) + self.led_buf = bytearray(self.leds * bpp) + self.timing = (((350, 850, 800, 400) if timing else (800, 1700, 1600, 900)) if isinstance(timing, int) else timing) + if not self.multiplex: self.pin.init(self.pin.OUT,value=default) + self.write() + + def __len__(self): + return self.rgbs + + def __setitem__(self, n, v): + for i in range(self.bpp): + self.rgb_buf[n * self.bpp + self.ORDER[i]] = v[i] + + def __getitem__(self, n): + return tuple(self.rgb_buf[n* self.bpp + self.ORDER[i]] for i in range(self.bpp)) + + def led_set(self, n, v): + for i in range(self.bpp): + self.led_buf[n * self.bpp + self.ORDER[i]] = v[i] + + def led_get(self, n): + return tuple(self.led_buf[n * self.bpp + self.ORDER[i]] for i in range(self.bpp)) + + def fill(self, v): + for i in range(self.bpp): + j = self.ORDER[i] + while j < self.rgbs * self.bpp: + self.rgb_buf[j] = v[i] + j += self.bpp + + def write(self): + if self.multiplex: self.pin.init(self.pin.OUT) + bitstream(self.pin, 0, self.timing, self.rgb_buf + self.led_buf) + if self.multiplex: self.pin.init(self.pin.IN) + + def color_chase(self,R, G, B, wait): + for i in range(self.rgbs): + self.__setitem__(i,(R, G, B)) + self.write() + sleep(wait/1000) + + def rainbow_cycle(self, wait, clear=True): + for j in range(255): + for i in range(self.rgbs): + rc_index = (i * 256 // self.rgbs) + j + self.__setitem__(i,self.wheel(rc_index & 255)) + self.write() + sleep(wait / 1000 / 256) + if clear: + self.fill((0, 0, 0)) + self.write() + + def wheel(self,pos): + if pos < 0 or pos > 255: + return (0, 0, 0) + elif pos < 85: + return (pos * 3, 255 - pos * 3, 0) + elif pos < 170: + pos -= 85 + return (255 - pos * 3, 0, pos * 3) + else: + pos -= 170 + return (0, pos * 3, 255 - pos * 3) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ws_lora.py b/mixly/boards/default_src/micropython/origin/build/lib/ws_lora.py new file mode 100644 index 00000000..ff74b959 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ws_lora.py @@ -0,0 +1,129 @@ +""" +WS_Lora Weather Station + +Micropython library for Weather Station /Lora +======================================================= + +#Preliminary composition 20220408 + +dahanzimin From the Mixly Team +""" +from json import dumps +from rfm98 import RFM98 +from ubinascii import hexlify +from machine import I2C,SoftI2C,unique_id + +names =(("编号","电量","风速","阵风","风向","雨量","温度","湿度","光照","紫外线指数","气压","信号强度"), + ("ID","Battery","Wind Speed","Gust","Wind Direction","Rainfall","Temperature","Humidity","Illumination","UVI","Atmospheric","RSSI")) + +class Weather(RFM98): + def __init__(self,spi,cs_pin,i2c=None): + '''对继承初始化配置''' + super().__init__(spi,cs_pin,frequency_mhz=433.92,signal_bandwidth=125E3,coding_rate=5,spreading_factor=11) + self._data=(None,None,None,None,None,None,None,None,None,None,None,None,None) + self._atmos=None + self._labels=[] + + if type(i2c) in [I2C,SoftI2C]: + if 0x76 in i2c.scan(): + import hp203x + self._atmos = hp203x.HP203X(i2c) + + def _data_deal(self,buffer): + '''对解码数据进行处理''' + if self._crc8(buffer[0:14]) == buffer[14]: + Device_ID = (buffer[1] & 0x0f) <<4 | buffer[2] >>4 + State_BAT = (buffer[2] & 0x08) >>3 + AVG_Swind = (buffer[3] | (buffer[2] & 0x01)<<8)/10 + Gust_Swind = (buffer[4] | (buffer[2] & 0x02)<<7)/10 + DIR_wind = buffer[5] | (buffer[2] & 0x04)<<6 + SUM_Rain = (buffer[7] | buffer[6] <<8 )/10 + Temp_F = ((buffer[9] | (buffer[8] & 0x0F)<<8)-400)/10 + Temp_C = round((Temp_F-32)/1.8,2) + Humidity = buffer[10] + Light_Lux = (buffer[12] | buffer[11] <<8 | (buffer[8] & 0x30)<<12)/10 + UVI = buffer[13] / 10 + Pa = self._atmos.pressure() if self._atmos else None + #待添加数据值(Temp_F,Humidity,Light_Lux,UVI)报错处理 + return Device_ID,1-State_BAT,AVG_Swind,Gust_Swind,DIR_wind,SUM_Rain,Temp_C,Humidity,Light_Lux,UVI,Pa,super().packet_rssi(),super().packet_snr() + else: + return False + + def _crc8(self,buffer): + '''对数据进行CRC校验''' + crc = 0x00 + for byte in buffer: + crc ^= byte + for _ in range(8): + if crc & 0x80: + crc = (crc << 1) ^ 0x31 + else: + crc = crc << 1 + return crc & 0xff # return the bottom 8 bits + + def label(self,*args): + '''标记气象站标签如 (id,long,lat)''' + for arg in args: + if len(arg) == 3: + flag=True + for label in self._labels: + if label['ws_id'] == arg[0]: + label.update({'long':arg[1],'lat':arg[2]}) + flag=False + if flag: + self._labels.append({'ws_id':arg[0],'long':arg[1],'lat':arg[2]}) + else: + raise AttributeError('Invalid Input , format is (id,long,lat)') + return self._labels + + def any(self): + '''判读是否有数据''' + buffer=super().recv() + if buffer: + if (len(buffer)>=15) & (buffer[0] == 0xD4): + self._data=self._data_deal(buffer) + return True + + def data(self,chinese=True): + '''获取气象数据''' + _name=names[0] if chinese else names[1] + info_dict={_name[0]:self._data[0], + _name[1]:"Normal" if self._data[1]==1 else "Low", + _name[2]:str(self._data[2])+'m/s', + _name[3]:str(self._data[3])+'m/s', + _name[4]:str(self._data[4])+'°', + _name[5]:str(self._data[5])+'mm', + _name[6]:str(self._data[6])+'℃', + _name[7]:str(self._data[7])+'%', + _name[8]:str(self._data[8])+'lux', + _name[9]:self._data[9], + _name[10]:str(self._data[10])+'hPa', + _name[11]:str(self._data[11])+'dBm'} + + for label in self._labels: + if label['ws_id'] == self._data[0]: + msg_list=[] + for info in info_dict: + msg_list.append({"label":info,"value":info_dict[info]}) + label_dict={"message":msg_list,'clientid':hexlify(unique_id())} + label_dict.update(label) + return self._data,dumps(info_dict),dumps(label_dict) + return self._data,dumps(info_dict),'null' + + def uart_mixio(self,topic="station"): + '''打包气象数据串口转发''' + info_dict={topic+"-"+str(self._data[0]): + {"电量":"正常" if self._data[1]==1 else "亏电", + "风速":self._data[2], + "阵风":self._data[3], + "风向":self._data[4], + "雨量":self._data[5], + "温度":self._data[6], + "湿度":self._data[7], + "光照":self._data[8], + "紫外线":self._data[9], + "大气压":self._data[10], + "信号强度":self._data[11]}} + + print(dumps(info_dict)) + return info_dict \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/origin/build/lib/ws_solo.py b/mixly/boards/default_src/micropython/origin/build/lib/ws_solo.py new file mode 100644 index 00000000..bd742ce7 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/ws_solo.py @@ -0,0 +1,138 @@ +""" +Weather_Solo + +Micropython library for the Weather_Solo(WIND & RAIN) +======================================================= + +#Preliminary composition 20231207 + +@dahanzimin From the Mixly Team +""" +import time +import math +from machine import Pin, ADC + +class Weather_WS: + + def __init__(self, pin, leaf=0.09, pulse=2): + Pin(pin, Pin.IN).irq(handler=self._ws_func, trigger=Pin.IRQ_FALLING) + self._wtime = time.ticks_ms() + self._distance = 2 * math.pi * leaf / pulse + self._pulse = 0 + + def _ws_func(self, pin): + if pin.value() == 0: + self._pulse += self._distance + + def _grade(self, speed): + if speed <= 0.2: + grade=0 + elif speed <=1.5: + grade=1 + elif speed <=3.3: + grade=2 + elif speed <=5.4: + grade=3 + elif speed <=7.9: + grade=4 + elif speed <=10.7: + grade=5 + elif speed <=13.8: + grade=6 + elif speed <=17.1: + grade=7 + elif speed <=20.7: + grade=8 + elif speed <=24.4: + grade=9 + elif speed <=28.4: + grade=10 + elif speed <=32.6: + grade=11 + else: + grade=12 + return grade + + def wind_speed(self): + time.sleep_ms(100) + speed = self._pulse / time.ticks_diff(time.ticks_ms(), self._wtime) * 1000 if self._pulse > 0 else 0 + self._wtime = time.ticks_ms() + self._pulse = 0 + return round(speed, 2), self._grade(speed) + +class Weather_WD: + + _DS = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"] + _DA = [0, 22.5, 45, 67.5, 90, 112.5, 135, 157.5, 180, 202.5, 225, 247.5, 270, 292.5, 315, 337.5] + + def __init__(self, pin): + self.adc = ADC(Pin(pin), atten=ADC.ATTN_11DB) + + def wind_direction(self): + values = [] + for _ in range(20): + values.append(self.adc.read_uv()/1000000) + time.sleep_ms(1) + ain = sum(values) / 20 + + if ain <=0.083: + dir=12 + elif ain <=0.135: + dir=14 + elif ain <=0.184: + dir=13 + elif ain <=0.253: + dir=0 + elif ain <=0.349: + dir=15 + elif ain <=0.421: + dir=10 + elif ain <=0.568: + dir=11 + elif ain <=0.761: + dir=2 + elif ain <=1.004: + dir=1 + elif ain <=1.273: + dir=8 + elif ain <=1.501: + dir=9 + elif ain <=1.826: + dir=6 + elif ain <=2.137: + dir=7 + elif ain <=2.308: + dir=4 + elif ain <=2.429: + dir=3 + else: + dir=5 + return self._DS[dir], self._DA[dir] + +class Weather_Rain: + + def __init__(self, pin, capacity=0.2794): + Pin(pin, Pin.IN).irq(handler=self._rain_func, trigger=Pin.IRQ_FALLING) + self._rtime = time.ticks_ms() + self._load = capacity + self._mean = 0 + self._count = 0 + + def _rain_func(self, pin): + if pin.value() == 0: + self._count += self._load + + def rain_count(self, time_s=3600): + if time.ticks_diff(time.ticks_ms(), self._rtime) // 1000 >= time_s: + self._mean = self._count / time.ticks_diff(time.ticks_ms(), self._rtime) * time_s * 1000 if self._count > 0 else 0 + self._rtime = time.ticks_ms() + self._count = 0 + return round(self._count, 2), round(self._mean, 4) + +#integration +class Weather_Solo(Weather_WD, Weather_WS, Weather_Rain): + + def __init__(self, pin_wd, pin_ws, pin_rain): + Weather_WD.__init__(self, pin_wd) + Weather_WS.__init__(self, pin_ws) + Weather_Rain.__init__(self, pin_rain) diff --git a/mixly/boards/default_src/micropython/origin/build/lib/xunfei.py b/mixly/boards/default_src/micropython/origin/build/lib/xunfei.py new file mode 100644 index 00000000..19e62428 --- /dev/null +++ b/mixly/boards/default_src/micropython/origin/build/lib/xunfei.py @@ -0,0 +1,286 @@ +""" +MINI_XUNFEI + +Micropython library for the MIC_ADC XUNFEI(ASR, LLM) +======================================================= +@dahanzimin From the Mixly Team + +""" +import time +import hmac +import json +import hashlib +import rtctime +import websocket +import adc_mic +from base64 import b64decode, b64encode +from urllib import urlencode, urlparse + +class Ws_Param: + def __init__(self, APPID, APIKey, APISecret, Spark_url): + self.APPID = APPID + self.APIKey = APIKey + self.APISecret = APISecret + self.url = Spark_url + self.urlparse = urlparse(Spark_url) + + def create_url(self): + date = rtctime.rfc1123_time() + signature_origin = "host: " + self.urlparse.netloc + "\n" + signature_origin += "date: " + date + "\n" + signature_origin += "GET " + self.urlparse.path + " HTTP/1.1" + signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'), digestmod=hashlib.sha256).digest() + signature_base64 = b64encode(signature_sha).decode('utf-8') + authorization_origin = ('api_key="{}", algorithm="hmac-sha256", headers="host date request-line", signature="{}"'.format(self.APIKey, signature_base64)) + authorization = b64encode(authorization_origin.encode('utf-8')).decode('utf-8') + headers = {"authorization": authorization, "date": date, "host": self.urlparse.netloc} + return self.url + '?' + urlencode(headers) + +#语音听写 +class ASR_WebSocket(Ws_Param): + def __init__(self, adcpin, APPID, APIKey, APISecret, url='ws://iat-api.xfyun.cn/v2/iat', sample_rate=8000): + super().__init__(APPID, APIKey, APISecret, url) + self.ws = None + self.rate = sample_rate + self.mic = adc_mic.ADCMic(adcpin, sample_rate=sample_rate) + self.business = { + "domain": "iat", + "language": "zh_cn", + "accent": "mandarin", + "vad_eos": 1000, + "nbest": 1, + "wbest": 1, + } + + def connect(self): + self.ws = websocket.connect(self.create_url()) + self.ws.settimeout(1000) + + def _frame(self, status, buf): + if status == 0: + return {"common": {"app_id": self.APPID}, "business": self.business, "data": {"status": status, "format": f"audio/L16;rate={self.rate}", "audio": str(b64encode(buf), 'utf-8'), "encoding": "raw"}} + else: + return {"data": {"status": status, "format": f"audio/L16;rate={self.rate}", "audio": str(b64encode(buf), 'utf-8'), "encoding": "raw"}} + + def on_message(self, message): + result = "" + msg = json.loads(message) + code = msg["code"] + if code != 0: + raise AttributeError("%s Code:%s" % (msg["message"], code)) + else: + data = msg["data"]["result"]["ws"] + for i in data: + for w in i["cw"]: + result += w["w"] + if msg["data"]["status"]== 2: + return result, False + return result, True + + def receive_messages(self): + msg = "" + while True: + t = self.on_message(self.ws.recv()) + msg += t[0] + if not t[1]: + break + return msg + + def run(self, seconds=3, pace=True): + try: + self.connect() + _state = 0 + ibuf = int(self.rate * 0.2) + _buf = bytearray(ibuf) + _size = int(ibuf * seconds * 10) #100ms/次 + self.mic.start() + if pace: print('[',end ="") + while _size > 0: + if self.mic.read_into(_buf): + _size -= ibuf + if pace: print('=',end ="") + # 第一帧处理 + if _state == 0: + d = self._frame(_state, _buf) + _state = 1 + # 中间帧处理 + else: + d = self._frame(_state, _buf) + self.ws.send(json.dumps(d)) + # 最后一帧处理 + self.mic.stop() + d = self._frame(2, b'\x00') + self.ws.send(json.dumps(d)) + if pace: print(']') + msg = self.receive_messages() + return msg + except Exception as e: + onboard_bot.pcm_en(False) #PCM关闭 + if "403 Forbidden" in str(e): + raise OSError("Access denied, Please try updating clock time") + else: + print("Run error: %s" % (e)) + finally: + self.mic.stop() + self.ws.close() + +#中英识别大模型 +class IAT_WebSocket(ASR_WebSocket): + def __init__(self, adcpin, APPID, APIKey, APISecret, url='ws://iat.xf-yun.com/v1', sample_rate=8000, accent="mandarin", res_id=None): + super().__init__(adcpin, APPID, APIKey, APISecret, url, sample_rate) + self.res_id = res_id + self.business = { + "domain": "slm", + "language": "zh_cn", + "accent": accent, + "result": { + "encoding": "utf8", + "compress": "raw", + "format": "plain" + } + } + + def _frame(self, status, buf): + if status == 0: + return {"header": {"status": status, "app_id": self.APPID, "res_id": self.res_id}, "parameter": {"iat": self.business}, "payload": {"audio": { "audio": str(b64encode(buf), 'utf-8'), "sample_rate": self.rate, "encoding": "raw"}}} + else: + return {"header": {"status": status, "app_id": self.APPID, "res_id": self.res_id}, "payload": {"audio": { "audio": str(b64encode(buf), 'utf-8'), "sample_rate": self.rate, "encoding": "raw"}}} + + def on_message(self, message): + result = "" + msg = json.loads(message) + code = msg['header']["code"] + if code != 0: + raise AttributeError("%s Code:%s" % (msg['header']["message"], code)) + else: + if "payload" in msg: + text = msg["payload"]["result"]["text"] + data = json.loads(b64decode(text).decode())['ws'] + for i in data: + for w in i["cw"]: + result += w["w"] + if msg["header"]["status"]== 2: + return result, False + return result, True + +#大模型 +class LLM_WebSocket(Ws_Param): + Model_url = { + "Spark Ultra-32K": ("ws://spark-api.xf-yun.com/v4.0/chat", "4.0Ultra"), + "Spark Max-32K": ("ws://spark-api.xf-yun.com/chat/max-32k", "max-32k"), + "Spark Max": ("ws://spark-api.xf-yun.com/v3.5/chat", "generalv3.5"), + "Spark Pro-128K": (" ws://spark-api.xf-yun.com/chat/pro-128k", "pro-128k"), + "Spark Pro": ("ws://spark-api.xf-yun.com/v3.1/chat", "generalv3"), + "Spark Lite": ("ws://spark-api.xf-yun.com/v1.1/chat", "lite"), + "Spark kjwx": ("ws://spark-openapi-n.cn-huabei-1.xf-yun.com/v1.1/chat_kjwx", "kjwx"), + "Spark X1-32K": ("ws://spark-api.xf-yun.com/v1/x1", "x1"), + "Spark Customize": ("ws://sparkcube-api.xf-yun.com/v1/customize", "max"), + } + + def __init__(self, APPID, APIKey, APISecret, model='Spark Ultra-32K', system="你是知识渊博的助理,习惯简短表达", answers=50): + self.ws = None + self.answers = answers + self._url = self.Model_url[model] if model in self.Model_url else model + super().__init__(APPID, APIKey, APISecret, self._url[0]) + self._function = [{}, []] #[回调函数, 功能描述] + self._messages = [{"role": "system", "content": system}] + + def connect(self): + self.ws = websocket.connect(self.create_url()) + self.ws.settimeout(1000) + + def _params(self): + d = { + "header": {"app_id": self.APPID}, + "parameter": { + "chat": { + "domain": self._url[1], + "random_threshold": 0.5, + "max_tokens": 2048, + "auditing": "default" + } + }, + "payload": { + "message": { + "text": self._messages + } + } + } + if self._function[1]: + d["payload"]["functions"] = {"text": self._function[1]} + self.ws.send(json.dumps(d)) + + def function_call(self, callback, name, description, params): + """功能回调名称, 描述, ((参数名, 类型, 描述), ...)""" + properties = {"type": "object", "properties":{}, "required":[]} + for arg in params: + if len(arg) >= 3: + properties["properties"][arg[0]] = {"type": arg[1], "description": arg[2]} + if arg[0] not in properties["required"]: + properties["required"].append(arg[0]) + else: + raise AttributeError('Invalid Input , format is (name, type, description)') + self._function[0][name] = callback + self._function[1].append({"name": name, "description": description, "parameters": properties}) + + def empty_history(self): + self._messages = [] + + def add_history(self, role, content): + self._messages.append({ + "role": role, + "content": content + }) + + def on_message(self, message, reas): + result = "" + msg = json.loads(message) + code = msg['header']['code'] + if code != 0: + raise AttributeError("%s Code:%s" % (msg["header"]["message"], code)) + else: + choices = msg["payload"]["choices"] + text = choices["text"][0] + #推理 + if "reasoning_content" in text and reas: + print("reasoning: ", text["reasoning_content"]) + #回调 + if "tool_calls" in text: + function = text['tool_calls'][0]['function'] + if str(function['name']) in self._function[0] and function['arguments']: + self._function[0][function['name']](json.loads(function['arguments'])) + if "function_call" in text: + if str(text['function_call']['name']) in self._function[0] and text['function_call']['arguments']: + self._function[0][text['function_call']['name']](json.loads(text['function_call']['arguments'])) + #答复 + if "content" in text: + result += text["content"] + if choices["status"] == 2: + return result, False + return result, True + + def receive_messages(self, reas): + msg = "" + while True: + t = self.on_message(self.ws.recv(), reas) + msg += t[0] + if not t[1]: + break + return msg + + def run(self, question, reas=True): + try: + self.connect() + self.add_history("user", question) + self._params() + while self.answers < len(self._messages): + del self._messages[0] + msg = self.receive_messages(reas) + return msg + except Exception as e: + if "403 Forbidden" in str(e): + raise OSError("Access denied, Please try updating clock time") + else: + print("Run error: %s" % (e)) + finally: + self.ws.close() diff --git a/mixly/boards/default_src/micropython/package.json b/mixly/boards/default_src/micropython/package.json new file mode 100644 index 00000000..dbc10c94 --- /dev/null +++ b/mixly/boards/default_src/micropython/package.json @@ -0,0 +1,33 @@ +{ + "name": "@mixly/micropython", + "version": "1.6.0", + "description": "适用于mixly的micropython模块", + "scripts": { + "build:dev": "webpack --config=webpack.dev.js", + "build:prod": "npm run build:examples & webpack --config=webpack.prod.js & npm run build:libraries", + "build:examples": "node ../../../scripts/build-examples.js -t special", + "build:examples:ob": "node ../../../scripts/build-examples.js -t special --obfuscate", + "build:libraries": "python ../../../scripts/build-libraries.py ../../default/micropython/build/lib", + "publish:board": "npm publish --registry https://registry.npmjs.org/" + }, + "main": "./export.js", + "author": "Mixly Team", + "keywords": [ + "mixly", + "mixly-plugin", + "micropython" + ], + "homepage": "https://gitee.com/bnu_mixly/mixly3/tree/master/boards/default_src/micropython", + "bugs": { + "url": "https://gitee.com/bnu_mixly/mixly3/issues" + }, + "repository": { + "type": "git", + "url": "https://gitee.com/bnu_mixly/mixly3.git", + "directory": "default_src/micropython" + }, + "publishConfig": { + "access": "public" + }, + "license": "Apache 2.0" +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/python_generator.js b/mixly/boards/default_src/micropython/python_generator.js new file mode 100644 index 00000000..52f02367 --- /dev/null +++ b/mixly/boards/default_src/micropython/python_generator.js @@ -0,0 +1,332 @@ +/* +Overrides for generic Python code generation. +*/ +import * as Blockly from 'blockly/core'; +import { Names } from '@mixly/python'; + +/** + * Python code generator. + * @type {!Blockly.Generator} + */ +export const Python = new Blockly.Generator('Python'); +Python.INDENT = " "; + +/** + * List of illegal variable names. + * This is not intended to be a security feature. Blockly is 100% client-side, + * so bypassing this list is trivial. This is intended to prevent users from + * accidentally clobbering a built-in object or function. + * @private + */ +Python.addReservedWords( + // import keyword + // print(','.join(sorted(keyword.kwlist))) + // https://docs.python.org/3/reference/lexical_analysis.html#keywords + // https://docs.python.org/2/reference/lexical_analysis.html#keywords + 'False,None,True,and,as,assert,break,class,continue,def,del,elif,else,' + + 'except,exec,finally,for,from,global,if,import,in,is,lambda,nonlocal,not,' + + 'or,pass,print,raise,return,try,while,with,yield,' + + // https://docs.python.org/3/library/constants.html + // https://docs.python.org/2/library/constants.html + 'NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,' + + // >>> print(','.join(sorted(dir(__builtins__)))) + // https://docs.python.org/3/library/functions.html + // https://docs.python.org/2/library/functions.html + 'ArithmeticError,AssertionError,AttributeError,BaseException,' + + 'BlockingIOError,BrokenPipeError,BufferError,BytesWarning,' + + 'ChildProcessError,ConnectionAbortedError,ConnectionError,' + + 'ConnectionRefusedError,ConnectionResetError,DeprecationWarning,EOFError,' + + 'Ellipsis,EnvironmentError,Exception,FileExistsError,FileNotFoundError,' + + 'FloatingPointError,FutureWarning,GeneratorExit,IOError,ImportError,' + + 'ImportWarning,IndentationError,IndexError,InterruptedError,' + + 'IsADirectoryError,KeyError,KeyboardInterrupt,LookupError,MemoryError,' + + 'ModuleNotFoundError,NameError,NotADirectoryError,NotImplemented,' + + 'NotImplementedError,OSError,OverflowError,PendingDeprecationWarning,' + + 'PermissionError,ProcessLookupError,RecursionError,ReferenceError,' + + 'ResourceWarning,RuntimeError,RuntimeWarning,StandardError,' + + 'StopAsyncIteration,StopIteration,SyntaxError,SyntaxWarning,SystemError,' + + 'SystemExit,TabError,TimeoutError,TypeError,UnboundLocalError,' + + 'UnicodeDecodeError,UnicodeEncodeError,UnicodeError,' + + 'UnicodeTranslateError,UnicodeWarning,UserWarning,ValueError,Warning,' + + 'ZeroDivisionError,_,__build_class__,__debug__,__doc__,__import__,' + + '__loader__,__name__,__package__,__spec__,abs,all,any,apply,ascii,' + + 'basestring,bin,bool,buffer,bytearray,bytes,callable,chr,classmethod,cmp,' + + 'coerce,compile,complex,copyright,credits,delattr,dict,dir,divmod,' + + 'enumerate,eval,exec,execfile,exit,file,filter,float,format,frozenset,' + + 'getattr,globals,hasattr,hash,help,hex,id,input,int,intern,isinstance,' + + 'issubclass,iter,len,license,list,locals,long,map,max,memoryview,min,' + + 'next,object,oct,open,ord,pow,print,property,quit,range,raw_input,reduce,' + + 'reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,' + + 'sum,super,tuple,type,unichr,unicode,vars,xrange,zip' +); + +/** + * Order of operation ENUMs. + * http://docs.python.org/reference/expressions.html#summary + */ +Python.ORDER_ATOMIC = 0; // 0 "" ... +Python.ORDER_COLLECTION = 1; // tuples, lists, dictionaries +Python.ORDER_STRING_CONVERSION = 1; // `expression...` +Python.ORDER_UNARY_POSTFIX = 1; // expr++ expr-- () [] . +Python.ORDER_UNARY_PREFIX = 2; // -expr !expr ~expr ++expr --expr +Python.ORDER_MEMBER = 2.1; // . [] +Python.ORDER_FUNCTION_CALL = 2.2; // () +Python.ORDER_EXPONENTIATION = 3; // ** +Python.ORDER_UNARY_SIGN = 4; // + - +Python.ORDER_BITWISE_NOT = 4; // ~ +Python.ORDER_MULTIPLICATIVE = 5; // * / // % +Python.ORDER_ADDITIVE = 6; // + - +Python.ORDER_BITWISE_SHIFT = 7; // << >> +Python.ORDER_BITWISE_AND = 8; // & +Python.ORDER_BITWISE_XOR = 9; // ^ +Python.ORDER_BITWISE_OR = 10; // | +Python.ORDER_RELATIONAL = 11; // in, not in, is, is not, +// <, <=, >, >=, <>, !=, == +Python.ORDER_EQUALITY = 11; // == != === !== +Python.ORDER_LOGICAL_NOT = 12; // not +Python.ORDER_LOGICAL_AND = 13; // and +Python.ORDER_LOGICAL_OR = 14; // or +Python.ORDER_ASSIGNMENT = 14; // = *= /= ~/= %= += -= <<= >>= &= ^= |= +Python.ORDER_CONDITIONAL = 15; // if else +Python.ORDER_LAMBDA = 16; // lambda +Python.ORDER_NONE = 99; // (...) + +/** + * List of outer-inner pairings that do NOT require parentheses. + * @type {!Array.>} + */ +Python.ORDER_OVERRIDES = [ + // (foo()).bar -> foo().bar + // (foo())[0] -> foo()[0] + [Python.ORDER_FUNCTION_CALL, Python.ORDER_MEMBER], + // (foo())() -> foo()() + [Python.ORDER_FUNCTION_CALL, Python.ORDER_FUNCTION_CALL], + // (foo.bar).baz -> foo.bar.baz + // (foo.bar)[0] -> foo.bar[0] + // (foo[0]).bar -> foo[0].bar + // (foo[0])[1] -> foo[0][1] + [Python.ORDER_MEMBER, Python.ORDER_MEMBER], + // (foo.bar)() -> foo.bar() + // (foo[0])() -> foo[0]() + [Python.ORDER_MEMBER, Python.ORDER_FUNCTION_CALL], + + // not (not foo) -> not not foo + // [Python.ORDER_LOGICAL_NOT, Python.ORDER_LOGICAL_NOT], + // a and (b and c) -> a and b and c + // [Python.ORDER_LOGICAL_AND, Python.ORDER_LOGICAL_AND], + // a or (b or c) -> a or b or c + // [Python.ORDER_LOGICAL_OR, Python.ORDER_LOGICAL_OR] +]; + +Python.init = function () { + /** + * Empty loops or conditionals are not allowed in Python. + */ + Python.PASS = this.INDENT + 'pass\n'; + // Create a dictionary of definitions to be printed before the code. + Python.definitions_ = Object.create(null); + // Create a dictionary mapping desired function names in definitions_ + // to actual function names (to avoid collisions with user functions). + Python.functionNames_ = Object.create(null); + Python.setups_ = Object.create(null); + Python.loops_ = Object.create(null); + Python.codeEnd_ = Object.create(null); + + if (!Python.variableDB_) { + Python.variableDB_ = new Names(Python.RESERVED_WORDS_); + } else { + Python.variableDB_.reset(); + } +} + +Python.finish = function (code) { + // Convert the definitions dictionary into a list. + if (code !== "") { + code = code.replace(/\n/g, '\n'); + code = code.replace(/\n\s+$/, '\n'); + } + var imports = []; + var definitions_var = []; //变量定义 + var definitions_fun = []; //函数定义 + for (var name in this.definitions_) { + var def = this.definitions_[name]; + if (name.indexOf('import') === 0) { + imports.push(def); + } else if (name.indexOf('var_declare') === 0) { + definitions_var.push(def); + } else { + definitions_fun.push(def); + } + } + if (imports.length) { + imports.push('\n'); + } + if (definitions_var.length) { + definitions_var.push('\n'); + } + if (definitions_fun.length) { + definitions_fun.push('\n'); + } + var functions = []; + for (var name in Python.functions_) { + functions.push(Python.functions_[name]); + } + if (functions.length) { + functions.push('\n'); + } + var setups = []; + for (var name in Python.setups_) { + setups.push(Python.setups_[name]); + } + if (setups.length) { + setups.push('\n'); + } + var loops = []; + for (var name in Python.loops_) { + loops.push(Python.loops_[name]); + } + var codeEnd = []; + for (var name in Python.codeEnd_) { + codeEnd.push(Python.codeEnd_[name]); + } + if (codeEnd.length !== 0) { + codeEnd.push('\n'); + } + let text = ''; + if (loops.length > 0) { + text = imports.join('\n') + definitions_var.join('\n') + definitions_fun.join('\n') + + functions.join('\n') + setups.join('') + code + 'while True:\n' + loops.join('') + codeEnd.join('\n'); + } else { + text = imports.join('\n') + definitions_var.join('\n') + definitions_fun.join('\n') + + functions.join('\n') + setups.join('') + code + codeEnd.join('\n'); + } + return text; +} + + +/** + * Naked values are top-level blocks with outputs that aren't plugged into + * anything. + * @param {string} line Line of generated code. + * @return {string} Legal line of code. + */ +Python.scrubNakedValue = function (line) { + return line + '\n'; +} + +/** + * Encode a string as a properly escaped Python string, complete with quotes. + * @param {string} string Text to encode. + * @return {string} Python string. + * @private + */ +Python.quote_ = function (string) { + // Can't use goog.string.quote since % must also be escaped. + string = string.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\\n'); + + // Follow the CPython behaviour of repr() for a non-byte string. + var quote = '\''; + if (string.indexOf('\'') !== -1) { + if (string.indexOf('"') === -1) { + quote = '"'; + } else { + string = string.replace(/'/g, '\\\''); + } + } + return quote + string + quote; +} + +/** + * Encode a string as a properly escaped multiline Python string, complete + * with quotes. + * @param {string} string Text to encode. + * @return {string} Python string. + * @private + */ +Python.multiline_quote_ = function (string) { + // Can't use goog.string.quote since % must also be escaped. + string = string.replace(/'''/g, '\\\'\\\'\\\''); + return '\'\'\'' + string + '\'\'\''; +} + +/** + * Common tasks for generating Python from blocks. + * Handles comments for the specified block and any connected value blocks. + * Calls any statements following this block. + * @param {!Blockly.Block} block The current block. + * @param {string} code The Python code created for this block. + * @param {boolean=} opt_thisOnly True to generate code for only this statement. + * @return {string} Python code with comments and subsequent blocks added. + * @private + */ +Python.scrub_ = function (block, code, opt_thisOnly) { + var commentCode = ''; + // Only collect comments for blocks that aren't inline. + if (!block.outputConnection || !block.outputConnection.targetConnection) { + // Collect comment for this block. + var comment = block.getCommentText(); + if (comment) { + comment = Blockly.utils.string.wrap(comment, + Python.COMMENT_WRAP - 3); + commentCode += Python.prefixLines(comment + '\n', '# '); + } + // Collect comments for all value arguments. + // Don't collect comments for nested statements. + for (var i = 0; i < block.inputList.length; i++) { + if (block.inputList[i].type == Blockly.INPUT_VALUE) { + var childBlock = block.inputList[i].connection.targetBlock(); + if (childBlock) { + var comment = Python.allNestedComments(childBlock); + if (comment) { + commentCode += Python.prefixLines(comment, '# '); + } + } + } + } + } + var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); + var nextCode = opt_thisOnly ? '' : Python.blockToCode(nextBlock); + return commentCode + code + nextCode; +} + +/** + * Gets a property and adjusts the value, taking into account indexing, and + * casts to an integer. + * @param {!Blockly.Block} block The block. + * @param {string} atId The property ID of the element to get. + * @param {number=} opt_delta Value to add. + * @param {boolean=} opt_negate Whether to negate the value. + * @return {string|number} + */ +Python.getAdjustedInt = function (block, atId, opt_delta, opt_negate) { + var delta = opt_delta || 0; + if (block.workspace.options.oneBasedIndex) { + delta--; + } + var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; + var atOrder = delta ? Python.ORDER_ADDITIVE : + Python.ORDER_NONE; + var at = Python.valueToCode(block, atId, atOrder) || defaultAtIndex; + + if (Blockly.isNumber(at)) { + // If the index is a naked number, adjust it right now. + at = parseInt(at, 10) + delta; + if (opt_negate) { + at = -at; + } + } else { + // If the index is dynamic, adjust it in code. + if (delta > 0) { + at = 'int(' + at + ' + ' + delta + ')'; + } else if (delta < 0) { + at = 'int(' + at + ' - ' + -delta + ')'; + } else { + at = 'int(' + at + ')'; + } + if (opt_negate) { + at = '-' + at; + } + } + return at; +} \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/template.xml b/mixly/boards/default_src/micropython/template.xml new file mode 100644 index 00000000..e69de29b diff --git a/mixly/boards/default_src/micropython/template/board-config-message.html b/mixly/boards/default_src/micropython/template/board-config-message.html new file mode 100644 index 00000000..1debec4d --- /dev/null +++ b/mixly/boards/default_src/micropython/template/board-config-message.html @@ -0,0 +1,14 @@ +
+
{{-d.title}}
+
+ {{# if (d.message) { }} +

+ {{-d.message}} +

+ {{# } }} +
+
\ No newline at end of file diff --git a/mixly/boards/default_src/micropython/webpack.common.js b/mixly/boards/default_src/micropython/webpack.common.js new file mode 100644 index 00000000..c1bb8a8c --- /dev/null +++ b/mixly/boards/default_src/micropython/webpack.common.js @@ -0,0 +1,11 @@ +const path = require("path"); +const common = require("../../../webpack.common"); +const { merge } = require("webpack-merge"); + +module.exports = merge(common, { + resolve: { + alias: { + '@mixly/python': path.resolve(__dirname, '../python') + } + } +}); \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/webpack.dev.js b/mixly/boards/default_src/micropython/webpack.dev.js new file mode 100644 index 00000000..4e14d69c --- /dev/null +++ b/mixly/boards/default_src/micropython/webpack.dev.js @@ -0,0 +1,21 @@ +const path = require("path"); +const common = require("./webpack.common"); +const { merge } = require("webpack-merge"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const ESLintPlugin = require('eslint-webpack-plugin'); + +module.exports = merge(common, { + mode: "development", + devtool: 'source-map', + plugins: [ + new ESLintPlugin({ + context: process.cwd(), + }), + new HtmlWebpackPlugin({ + inject: false, + template: path.resolve(process.cwd(), 'template.xml'), + filename: 'index.xml', + minify: false + }) + ] +}); \ No newline at end of file diff --git a/mixly/boards/default_src/micropython/webpack.prod.js b/mixly/boards/default_src/micropython/webpack.prod.js new file mode 100644 index 00000000..0e9f3265 --- /dev/null +++ b/mixly/boards/default_src/micropython/webpack.prod.js @@ -0,0 +1,27 @@ +const path = require("path"); +const common = require("./webpack.common"); +const { merge } = require("webpack-merge"); +const TerserPlugin = require("terser-webpack-plugin"); +var HtmlWebpackPlugin = require("html-webpack-plugin"); + +module.exports = merge(common, { + mode: "production", + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + extractComments: false, + }), + new HtmlWebpackPlugin({ + inject: false, + template: path.resolve(process.cwd(), 'template.xml'), + filename: 'index.xml', + minify: { + removeAttributeQuotes: true, + collapseWhitespace: true, + removeComments: true, + } + }) + ] + } +}); \ No newline at end of file diff --git a/mixly/boards/default_src/python/.npmignore b/mixly/boards/default_src/python/.npmignore new file mode 100644 index 00000000..21ab2a3e --- /dev/null +++ b/mixly/boards/default_src/python/.npmignore @@ -0,0 +1,3 @@ +node_modules +build +origin \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/class.js b/mixly/boards/default_src/python/blocks/class.js new file mode 100644 index 00000000..319ca04c --- /dev/null +++ b/mixly/boards/default_src/python/blocks/class.js @@ -0,0 +1,1163 @@ +import * as Blockly from 'blockly/core'; + +const CLASS_HUE = 345;//'#af5180'//330; +const PROPERTY_HUE = 345; +const METHOD_HUE = 345; +const OBJECT_HUE = 345; + +export const class_make = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.CREATE_CLASS) + .appendField(new Blockly.FieldTextInput(""), "VAR"); + this.appendStatementInput("data") + .setCheck(null) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setColour(CLASS_HUE); + this.setTooltip(""); + this.setHelpUrl(""); + }, + class_getVars: function () { + var varValue = this.getFieldValue('VAR'); + if (varValue == null) { + return []; + } + return varValue.split(","); + }, + class_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + } +}; + +export const class_make_with_base = { + init: function () { + this.appendValueInput("NAME") + .appendField(Blockly.Msg.CREATE_CLASS) + .appendField(new Blockly.FieldTextInput(""), "VAR") + .appendField(" " + Blockly.Msg.FATHER_CLASS + ":"); + this.appendStatementInput("data") + .setCheck(null) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setColour(CLASS_HUE); + this.setTooltip(""); + this.setHelpUrl(""); + }, + class_getVars: function () { + var varValue = this.getFieldValue('VAR'); + if (varValue == null) { + return []; + } + return varValue.split(","); + }, + class_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + } +}; + +export const class_get = { + init: function () { + this.setColour(CLASS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_CLASS) + .appendField(new Blockly.FieldTextInput(''), 'VAR'); + this.setOutput(true); + this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP); + }, + class_getVars: function () { + return [this.getFieldValue('VAR')]; + }, + class_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + } +}; + +export const property_set = { + init: function () { + this.setColour(PROPERTY_HUE); + this.appendValueInput('VALUE'); + this.appendValueInput('DATA') + .appendField(Blockly.Msg.MIXPY_ATTRIBUTE_OF) + .appendField(new Blockly.FieldTextInput(''), 'VAR') + .appendField(" " + Blockly.Msg.MIXLY_VALUE2 + " "); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP); + }, + property_getVars: function () { + var varValue = this.getFieldValue('VAR'); + if (varValue == null) { + return []; + } + return varValue.split(","); + }, + property_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + } +}; + +export const property_get = { + init: function () { + this.setColour(PROPERTY_HUE); + this.appendValueInput('VALUE'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_ATTRIBUTE_OF) + .appendField(new Blockly.FieldTextInput(''), 'VAR'); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP); + }, + property_getVars: function () { + return [this.getFieldValue('VAR')]; + }, + property_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + } +}; + +/** + * Common HSV hue for all blocks in this category. + */ +export const method_procedures_defnoreturn = { + /** + * Block for defining a procedure with no return value. + * @this Blockly.Block + */ + init: function () { + this.setColour(METHOD_HUE); + var nameField = new Blockly.FieldTextInput( + Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE, + Blockly.Class.prorename); + nameField.setSpellcheck(false); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_CREATE_METHOD) + .appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE) + .appendField(nameField, 'NAME') + .appendField('', 'PARAMS'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['method_procedures_mutatorarg'], this)); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP); + this.arguments_ = []; + this.argumentstype_ = [];//新增 + this.setStatements_(true); + this.statementConnection_ = null; + }, + /** + * Add or remove the statement block from this function definition. + * @param {boolean} hasStatements True if a statement block is needed. + * @this Blockly.Block + */ + setStatements_: function (hasStatements) { + if (this.hasStatements_ === hasStatements) { + return; + } + if (hasStatements) { + this.appendStatementInput('STACK') + .appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO); + if (this.getInput('RETURN')) { + this.moveInputBefore('STACK', 'RETURN'); + } + } else { + this.removeInput('STACK', true); + } + this.hasStatements_ = hasStatements; + }, + /** + * Update the display of parameters for this procedure definition block. + * Display a warning if there are duplicately named parameters. + * @private + * @this Blockly.Block + */ + updateParams_: function () { + // Check for duplicated arguments. + var badArg = false; + var hash = {}; + for (var i = 0; i < this.arguments_.length; i++) { + if (hash['arg_' + this.arguments_[i].toLowerCase()]) { + badArg = true; + break; + } + hash['arg_' + this.arguments_[i].toLowerCase()] = true; + } + if (badArg) { + this.setWarningText(Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING); + } else { + this.setWarningText(null); + } + // Merge the arguments into a human-readable list. + var paramString = ''; + if (this.arguments_.length) { + paramString = Blockly.Msg.PROCEDURES_BEFORE_PARAMS + + ' ' + this.arguments_.join(', '); + } + // The params field is deterministic based on the mutation, + // no need to fire a change event. + Blockly.Events.disable(); + this.setFieldValue(paramString, 'PARAMS'); + Blockly.Events.enable(); + }, + /** + * Create XML to represent the argument inputs. + * @param {=boolean} opt_paramIds If true include the IDs of the parameter + * quarks. Used by Blockly.Procedures.mutateCallers for reconnection. + * @return {!Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + for (var i = 0; i < this.arguments_.length; i++) { + var parameter = document.createElement('arg'); + parameter.setAttribute('name', this.arguments_[i]); + //parameter.setAttribute('vartype', this.argumentstype_[i]);//新增 + container.appendChild(parameter); + } + + // Save whether the statement input is visible. + if (!this.hasStatements_) { + container.setAttribute('statements', 'false'); + } + return container; + }, + /** + * Parse XML to restore the argument inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.arguments_ = []; + this.argumentstype_ = [];//新增 + for (var i = 0; xmlElement.childNodes[i]; i++) { + let childNode = xmlElement.childNodes[i]; + if (childNode.nodeName.toLowerCase() == 'arg') { + this.arguments_.push(childNode.getAttribute('name')); + //this.argumentstype_.push(childNode.getAttribute('vartype'));//新增 + } + } + this.updateParams_(); + Blockly.Class.mutateCallers(this); + + // Show or hide the statement input. + this.setStatements_(xmlElement.getAttribute('statements') !== 'false'); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = workspace.newBlock('method_procedures_mutatorcontainer'); + containerBlock.initSvg(); + + // Check/uncheck the allow statement box. + if (this.getInput('RETURN')) { + containerBlock.setFieldValue(this.hasStatements_ ? 'TRUE' : 'FALSE', + 'STATEMENTS'); + } else { + containerBlock.getInput('STATEMENT_INPUT').setVisible(false); + } + + // Parameter list. + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.arguments_.length; i++) { + var paramBlock = workspace.newBlock('method_procedures_mutatorarg'); + paramBlock.initSvg(); + paramBlock.setFieldValue(this.arguments_[i], 'NAME'); + //paramBlock.setFieldValue(this.argumentstype_[i], 'TYPEVAR');//新增 + // Store the old location. + paramBlock.oldLocation = i; + connection.connect(paramBlock.previousConnection); + connection = paramBlock.nextConnection; + } + // Initialize procedure's callers with blank IDs. + //Blockly.Class.promutateCallers(this); + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + // Parameter list. + this.arguments_ = []; + this.paramIds_ = []; + this.argumentstype_ = [];//新增 + var paramBlock = containerBlock.getInputTargetBlock('STACK'); + while (paramBlock) { + this.arguments_.push(paramBlock.getFieldValue('NAME')); + //this.argumentstype_.push(paramBlock.getFieldValue('TYPEVAR'));//新增 + this.paramIds_.push(paramBlock.id); + paramBlock = paramBlock.nextConnection && + paramBlock.nextConnection.targetBlock(); + } + this.updateParams_(); + Blockly.Class.promutateCallers(this); + + // Show/hide the statement input. + var hasStatements = containerBlock.getFieldValue('STATEMENTS'); + if (hasStatements !== null) { + hasStatements = hasStatements == 'TRUE'; + if (this.hasStatements_ != hasStatements) { + if (hasStatements) { + this.setStatements_(true); + // Restore the stack, if one was saved. + this.statementConnection_ && this.statementConnection_.reconnect(this, 'STACK'); + this.statementConnection_ = null; + } else { + // Save the stack, then disconnect it. + var stackConnection = this.getInput('STACK').connection; + this.statementConnection_ = stackConnection.targetConnection; + if (this.statementConnection_) { + var stackBlock = stackConnection.targetBlock(); + stackBlock.unplug(); + stackBlock.bumpNeighbours_(); + } + this.setStatements_(false); + } + } + } + }, + /** + * Dispose of any callers. + * @this Blockly.Block + */ + /* + dispose: function() { + var name = this.getFieldValue('NAME'); + Blockly.Class.prodisposeCallers(name, this.workspace); + // Call parent's destructor. + this.constructor.prototype.dispose.apply(this, arguments); + },*/ + + /** + * Return the signature of this procedure definition. + * @return {!Array} Tuple containing three elements: + * - the name of the defined procedure, + * - a list of all its arguments, + * - that it DOES NOT have a return value. + * @this Blockly.Block + */ + method_getProcedureDef: function () { + var surround_parent = this.getSurroundParent(); + var arg_data = ''; + for (var i = 0; i < this.arguments_.length; i++) { + arg_data = arg_data + '_' + this.arguments_[i]; + } + if (surround_parent && ((surround_parent.type == 'class_make') || (surround_parent.type == 'class_make_with_base'))) { + var class_name = surround_parent.getFieldValue('VAR'); + return [this.getFieldValue('NAME'), this.arguments_, false, this.getFieldValue('NAME') + '_' + class_name, this.getFieldValue('NAME') + arg_data]; + } + return [this.getFieldValue('NAME'), this.arguments_, false, this.getFieldValue('NAME'), this.getFieldValue('NAME') + arg_data]; + }, + /** + * Return all variables referenced by this block. + * @return {!Array.} List of variable names. + * @this Blockly.Block + */ + getVars: function () { + return this.arguments_; + }, + /** + * Notification that a variable is renaming. + * If the name matches one of this block's variables, rename it. + * @param {string} oldName Previous name of variable. + * @param {string} newName Renamed variable. + * @this Blockly.Block + */ + renameVar: function (oldName, newName) { + var change = false; + for (var i = 0; i < this.arguments_.length; i++) { + if (Blockly.Names.equals(oldName, this.arguments_[i])) { + this.arguments_[i] = newName; + change = true; + } + } + if (change) { + this.updateParams_(); + // Update the mutator's variables if the mutator is open. + if (this.mutator.isVisible()) { + var blocks = this.mutator.workspace_.getAllBlocks(); + for (var i = 0; blocks[i]; i++) { + let block = blocks[i]; + if (block.type == 'method_procedures_mutatorarg' && + Blockly.Names.equals(oldName, block.getFieldValue('NAME'))) { + block.setFieldValue(newName, 'NAME'); + } + } + } + } + }, + /** + * Add custom menu options to this block's context menu. + * @param {!Array} options List of menu options to add to. + * @this Blockly.Block + */ + customContextMenu: function (options) { + // Add option to create caller. + var option = { enabled: true }; + var name = this.getFieldValue('NAME'); + option.text = Blockly.Msg.PROCEDURES_CREATE_DO.replace('%1', name); + var xmlMutation = Blockly.utils.xml.createElement('mutation'); + xmlMutation.setAttribute('name', name); + for (var i = 0; i < this.arguments_.length; i++) { + var xmlArg = Blockly.utils.xml.createElement('arg'); + xmlArg.setAttribute('name', this.arguments_[i]); + //xmlArg.setAttribute('type', this.argumentstype_[i]);//新增 + xmlMutation.appendChild(xmlArg); + } + var xmlBlock = Blockly.utils.xml.createElement('block', null, xmlMutation); + xmlBlock.setAttribute('type', this.callType_); + option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock); + options.push(option); + + // Add options to create getters for each parameter. + if (!this.isCollapsed()) { + for (var i = 0; i < this.arguments_.length; i++) { + var option = { enabled: true }; + var name = this.arguments_[i]; + option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name); + var xmlField = Blockly.utils.xml.createElement('field', null, name); + xmlField.setAttribute('name', 'VAR'); + xmlField.setAttribute('type', 'TYPEVAR');//新增 + var xmlBlock = Blockly.utils.xml.createElement('block', null, xmlField); + xmlBlock.setAttribute('type', 'variables_get'); + option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock); + options.push(option); + } + } + }, + callType_: 'method_procedures_callnoreturn' +}; + +export const method_procedures_defreturn = { + /** + * Block for defining a procedure with a return value. + * @this Blockly.Block + */ + init: function () { + this.setColour(METHOD_HUE); + var nameField = new Blockly.FieldTextInput( + Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE, + Blockly.Class.prorename); + nameField.setSpellcheck(false); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_CREATE_METHOD) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE) + .appendField(nameField, 'NAME') + .appendField('', 'PARAMS'); + this.appendValueInput('RETURN') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['method_procedures_mutatorarg'], this)); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP); + this.arguments_ = []; + this.setStatements_(true); + this.statementConnection_ = null; + }, + setStatements_: method_procedures_defnoreturn.setStatements_, + updateParams_: method_procedures_defnoreturn.updateParams_, + mutationToDom: method_procedures_defnoreturn.mutationToDom, + domToMutation: method_procedures_defnoreturn.domToMutation, + decompose: method_procedures_defnoreturn.decompose, + compose: method_procedures_defnoreturn.compose, + dispose: method_procedures_defnoreturn.dispose, + /** + * Return the signature of this procedure definition. + * @return {!Array} Tuple containing three elements: + * - the name of the defined procedure, + * - a list of all its arguments, + * - that it DOES have a return value. + * @this Blockly.Block + */ + method_getProcedureDef: function () { + var surround_parent = this.getSurroundParent(); + var arg_data = ''; + for (var i = 0; i < this.arguments_.length; i++) { + arg_data = arg_data + '_' + this.arguments_[i]; + } + if (surround_parent && ((surround_parent.type == 'class_make') || (surround_parent.type == 'class_make_with_base'))) { + var class_name = surround_parent.getFieldValue('VAR'); + return [this.getFieldValue('NAME'), this.arguments_, true, this.getFieldValue('NAME') + '_' + class_name, this.getFieldValue('NAME') + arg_data]; + } + return [this.getFieldValue('NAME'), this.arguments_, true, this.getFieldValue('NAME'), this.getFieldValue('NAME') + arg_data]; + }, + getVars: method_procedures_defnoreturn.getVars, + renameVar: method_procedures_defnoreturn.renameVar, + customContextMenu: method_procedures_defnoreturn.customContextMenu, + callType_: 'method_procedures_callreturn' +}; + +export const method_procedures_mutatorcontainer = { + /** + * Mutator block for procedure container. + * @this Blockly.Block + */ + init: function () { + this.setColour(METHOD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE); + this.appendStatementInput('STACK'); + this.appendDummyInput('STATEMENT_INPUT') + .appendField(Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS) + .appendField(new Blockly.FieldCheckbox('TRUE'), 'STATEMENTS'); + this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const method_procedures_mutatorarg = { + /** + * Mutator block for procedure argument. + * @this Blockly.Block + */ + init: function () { + this.setColour(METHOD_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.PROCEDURES_BEFORE_PARAMS) + //.appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'number'], [Blockly.Msg.LANG_MATH_STRING, 'string'], [Blockly.Msg.LANG_MATH_BOOLEAN, 'boolean'], [Blockly.Msg.MIXLY_MICROBIT_JS_TYPE_ARRAY_NUMBER, 'Array'], [Blockly.Msg.MIXLY_MICROBIT_JS_TYPE_ARRAY_STRING, 'Array']]), 'TYPEVAR') + .appendField(new Blockly.FieldTextInput('x', this.validator_), 'NAME'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP); + this.contextMenu = false; + }, + /** + * Obtain a valid name for the procedure. + * Merge runs of whitespace. Strip leading and trailing whitespace. + * Beyond this, all names are legal. + * @param {string} newVar User-supplied name. + * @return {?string} Valid name, or null if a name was not specified. + * @private + * @this Blockly.Block + */ + validator_: function (newVar) { + newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, ''); + return newVar || null; + } +}; + +export const method_procedures_callnoreturn = { + /** + * Block for calling a procedure with no return value. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL); + this.setColour(METHOD_HUE); + this.appendValueInput('DATA'); + this.appendDummyInput('TOPROW') + .appendField(Blockly.Msg.MIXPY_EXECUTION_METHOD) + .appendField(this.id, 'NAME'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + // Tooltip is set in method_renameProcedure. + this.arguments_ = []; + this.quarkConnections_ = {}; + this.quarkIds_ = null; + }, + /** + * Returns the name of the procedure this block calls. + * @return {string} Procedure name. + * @this Blockly.Block + */ + method_getProcedureCall: function () { + // The NAME field is guaranteed to exist, null will never be returned. + return /** @type {string} */ (this.getFieldValue('NAME')); + }, + /** + * Notification that a procedure is renaming. + * If the name matches this block's procedure, rename it. + * @param {string} oldName Previous name of procedure. + * @param {string} newName Renamed procedure. + * @this Blockly.Block + */ + method_renameProcedure: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.method_getProcedureCall())) { + this.setFieldValue(newName, 'NAME'); + this.setTooltip( + (this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP : + Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP) + .replace('%1', newName)); + } + }, + /** + * Notification that the procedure's parameters have changed. + * @param {!Array.} paramNames New param names, e.g. ['x', 'y', 'z']. + * @param {!Array.} paramIds IDs of params (consistent for each + * parameter through the life of a mutator, regardless of param renaming), + * e.g. ['piua', 'f8b_', 'oi.o']. + * @private + * @this Blockly.Block + */ + setProcedureParameters_: function (paramNames, paramIds) { + // Data structures: + // this.arguments = ['x', 'y'] + // Existing param names. + // this.quarkConnections_ {piua: null, f8b_: Blockly.Connection} + // Look-up of paramIds to connections plugged into the call block. + // this.quarkIds_ = ['piua', 'f8b_'] + // Existing param IDs. + // Note that quarkConnections_ may include IDs that no longer exist, but + // which might reappear if a param is reattached in the mutator. + var defBlock = Blockly.Class.progetDefinition(this.method_getProcedureCall(), + this.workspace); + const mutatorIcon = defBlock && defBlock.getIcon(Blockly.icons.MutatorIcon.TYPE); + const mutatorOpen = + mutatorIcon && mutatorIcon.bubbleIsVisible(); + if (!mutatorOpen) { + this.quarkConnections_ = {}; + this.quarkIds_ = null; + } + if (!paramIds) { + // Reset the quarks (a mutator is about to open). + return; + } + if (this.arguments_.length) { + if (Blockly.Names.equals(this.arguments_, paramNames)) { + // No change. + this.quarkIds_ = paramIds; + return; + } + } + if (paramIds.length != paramNames.length) { + throw 'Error: paramNames and paramIds must be the same length.'; + } + this.setCollapsed(false); + if (!this.quarkIds_) { + // Initialize tracking for this block. + this.quarkConnections_ = {}; + if (paramNames.join('\n') == this.arguments_.join('\n')) { + // No change to the parameters, allow quarkConnections_ to be + // populated with the existing connections. + this.quarkIds_ = paramIds; + } else { + this.quarkIds_ = []; + } + } + // Switch off rendering while the block is rebuilt. + var savedRendered = this.rendered; + this.rendered = false; + // Update the quarkConnections_ with existing connections. + for (var i = 1; i < this.arguments_.length; i++) { + var input = this.getInput('ARG' + i); + if (input) { + var connection = input.connection.targetConnection; + this.quarkConnections_[this.quarkIds_[i]] = connection; + if (mutatorOpen && connection && + paramIds.indexOf(this.quarkIds_[i]) == -1) { + // This connection should no longer be attached to this block. + connection.disconnect(); + connection.getSourceBlock().bumpNeighbours_(); + } + } + } + // Rebuild the block's arguments. + this.arguments_ = [].concat(paramNames); + this.updateShape_(); + this.quarkIds_ = paramIds; + // Reconnect any child blocks. + if (this.quarkIds_) { + for (var i = 1; i < this.arguments_.length; i++) { + var quarkId = this.quarkIds_[i]; + if (quarkId in this.quarkConnections_) { + var connection = this.quarkConnections_[quarkId]; + if (connection && !connection.reconnect(this, 'ARG' + i)) { + // Block no longer exists or has been attached elsewhere. + delete this.quarkConnections_[quarkId]; + } + } + } + } + // Restore rendering and show the changes. + this.rendered = savedRendered; + if (this.rendered) { + this.render(); + } + }, + /** + * Modify this block to have the correct number of arguments. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + for (var i = 1; i < this.arguments_.length; i++) { + var field = this.getField('ARGNAME' + i); + if (field) { + // Ensure argument name is up to date. + // The argument name field is deterministic based on the mutation, + // no need to fire a change event. + Blockly.Events.disable(); + field.setValue(this.arguments_[i]); + Blockly.Events.enable(); + } else { + // Add new input. + field = new Blockly.FieldLabel(this.arguments_[i]); + var input = this.appendValueInput('ARG' + i) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(field, 'ARGNAME' + i); + input.init(); + } + } + // Remove deleted inputs. + while (this.getInput('ARG' + i)) { + this.removeInput('ARG' + i); + i++; + } + // Add 'with:' if there are parameters, remove otherwise. + var topRow = this.getInput('TOPROW'); + if (topRow) { + if (this.arguments_.length - 1) { + if (!this.getField('WITH')) { + topRow.appendField(Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS, 'WITH'); + topRow.init(); + } + } else { + if (this.getField('WITH')) { + topRow.removeField('WITH'); + } + } + } + }, + /** + * Create XML to represent the (non-editable) name and arguments. + * @return {!Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('name', this.method_getProcedureCall()); + for (var i = 0; i < this.arguments_.length; i++) { + var parameter = document.createElement('arg'); + parameter.setAttribute('name', this.arguments_[i]); + container.appendChild(parameter); + } + return container; + }, + /** + * Parse XML to restore the (non-editable) name and parameters. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var name = xmlElement.getAttribute('name'); + this.method_renameProcedure(this.method_getProcedureCall(), name); + var args = []; + var paramIds = []; + for (var i = 0; xmlElement.childNodes[i]; i++) { + let childNode = xmlElement.childNodes[i]; + if (childNode.nodeName.toLowerCase() == 'arg') { + args.push(childNode.getAttribute('name')); + paramIds.push(childNode.getAttribute('paramId')); + } + } + this.setProcedureParameters_(args, paramIds); + }, + /** + * Notification that a variable is renaming. + * If the name matches one of this block's variables, rename it. + * @param {string} oldName Previous name of variable. + * @param {string} newName Renamed variable. + * @this Blockly.Block + */ + renameVar: function (oldName, newName) { + for (var i = 1; i < this.arguments_.length; i++) { + if (Blockly.Names.equals(oldName, this.arguments_[i])) { + this.arguments_[i] = newName; + this.getField('ARGNAME' + i).setValue(newName); + } + } + }, + /** + * Add menu option to find the definition block for this call. + * @param {!Array} options List of menu options to add to. + * @this Blockly.Block + */ + customContextMenu: function (options) { + var option = { enabled: true }; + option.text = Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF; + var name = this.method_getProcedureCall(); + var workspace = this.workspace; + option.callback = function () { + var def = Blockly.Class.progetDefinition(name, workspace); + def && def.select(); + }; + options.push(option); + } +}; + +export const method_procedures_callreturn = { + /** + * Block for calling a procedure with a return value. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL); + this.setColour(METHOD_HUE); + this.appendValueInput('DATA'); + this.appendDummyInput('TOPROW') + .appendField(Blockly.Msg.MIXPY_EXECUTION_METHOD) + .appendField(Blockly.Msg.PROCEDURES_CALLRETURN_CALL) + .appendField('', 'NAME'); + this.setOutput(true); + this.setInputsInline(true); + // Tooltip is set in domToMutation. + this.arguments_ = []; + this.quarkConnections_ = {}; + this.quarkIds_ = null; + }, + method_getProcedureCall: method_procedures_callnoreturn.method_getProcedureCall, + method_renameProcedure: method_procedures_callnoreturn.method_renameProcedure, + setProcedureParameters_: + method_procedures_callnoreturn.setProcedureParameters_, + updateShape_: method_procedures_callnoreturn.updateShape_, + mutationToDom: method_procedures_callnoreturn.mutationToDom, + domToMutation: method_procedures_callnoreturn.domToMutation, + renameVar: method_procedures_callnoreturn.renameVar, + customContextMenu: method_procedures_callnoreturn.customContextMenu +}; + +export const method_procedures_ifreturn = { + /** + * Block for conditionally returning a value from a procedure. + * @this Blockly.Block + */ + init: function () { + this.setColour(METHOD_HUE); + this.appendValueInput('CONDITION') + .setCheck(Boolean) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP); + this.hasReturnValue_ = true; + }, + /** + * Create XML to represent whether this block has a return value. + * @return {!Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('value', Number(this.hasReturnValue_)); + return container; + }, + /** + * Parse XML to restore whether this block has a return value. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var value = xmlElement.getAttribute('value'); + this.hasReturnValue_ = (value == 1); + if (!this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + } + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if this flow block is not nested inside a loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function () { + var legal = false; + // Is the block nested in a procedure? + var block = this; + do { + if (this.FUNCTION_TYPES.indexOf(block.type) != -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + // If needed, toggle whether this block has a return value. + if (block.type == 'method_procedures_defnoreturn' && this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = false; + } else if (block.type == 'method_procedures_defreturn' && + !this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = true; + } + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING); + } + }, + /** + * List of block types that are functions and thus do not need warnings. + * To add a new function type add this to your code: + * procedures_ifreturn.FUNCTION_TYPES.push('custom_func'); + */ + FUNCTION_TYPES: ['method_procedures_defnoreturn', 'method_procedures_defreturn'] +}; + + +export const method_procedures_return = { + /** + * Block for conditionally returning a value from a procedure. + * @this Blockly.Block + */ + init: function () { + this.setColour(METHOD_HUE); + // this.appendValueInput('CONDITION') + // .setCheck(Boolean) + // .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP); + this.hasReturnValue_ = true; + }, + /** + * Create XML to represent whether this block has a return value. + * @return {!Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('value', Number(this.hasReturnValue_)); + return container; + }, + /** + * Parse XML to restore whether this block has a return value. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var value = xmlElement.getAttribute('value'); + this.hasReturnValue_ = (value == 1); + if (!this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + } + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if this flow block is not nested inside a loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function () { + var legal = false; + // Is the block nested in a procedure? + var block = this; + do { + if (this.FUNCTION_TYPES.indexOf(block.type) != -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + // If needed, toggle whether this block has a return value. + if (block.type == 'method_procedures_defnoreturn' && this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = false; + } else if (block.type == 'method_procedures_defreturn' && + !this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = true; + } + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING); + } + }, + /** + * List of block types that are functions and thus do not need warnings. + * To add a new function type add this to your code: + * procedures_ifreturn.FUNCTION_TYPES.push('custom_func'); + */ + FUNCTION_TYPES: ['method_procedures_defnoreturn', 'method_procedures_defreturn'] +}; + +export const object_set = { + init: function () { + this.appendDummyInput("EMPTY") + .appendField(Blockly.Msg.MIXPY_OBJECT) + .appendField(new Blockly.FieldTextInput(""), "VAR11") + .appendField(" " + Blockly.Msg.MIXLY_VALUE2 + " " + Blockly.Msg.MIXPY_CLASS) + .appendField(new Blockly.FieldTextInput(""), "VAR10"); + this.itemCount_ = 0; + this.updateShape_(); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setColour(OBJECT_HUE); + this.setMutator(new Blockly.icons.MutatorIcon(['object_set_with_item'], this)); + this.setTooltip(""); + this.setHelpUrl(""); + }, + class_getVars: function () { + return [this.getFieldValue('VAR10')]; + }, + class_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR10'))) { + this.setFieldValue(newName, 'VAR10'); + } + }, + object_getVars: function () { + var varValue = this.getFieldValue('VAR11'); + if (varValue == null) { + return []; + } + return varValue.split(","); + }, + object_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR11'))) { + this.setFieldValue(newName, 'VAR11'); + } + }, + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('object_set_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('object_set_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + updateShape_: function () { + // Delete everything. + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + // Rebuild block. + if (this.itemCount_ != 0) { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + input.setAlign(Blockly.inputs.Align.RIGHT) + input.appendField(Blockly.Msg.MIXLY_PARAMS + (i + 1) + ":"); + } + } + } +}; + +export const object_set_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(OBJECT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_ADD_PARAMETERS); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const object_set_with_container = { + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(OBJECT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.appendStatementInput('STACK'); + this.setTooltip(""); + this.contextMenu = false; + } +}; + +export const object_get = { + init: function () { + this.setColour(OBJECT_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_OBJECT) + .appendField(new Blockly.FieldTextInput(''), 'VAR'); + this.setOutput(true); + this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP); + }, + object_getVars: function () { + return [this.getFieldValue('VAR')]; + }, + object_renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + } +}; + diff --git a/mixly/boards/default_src/python/blocks/control.js b/mixly/boards/default_src/python/blocks/control.js new file mode 100644 index 00000000..7ddfba17 --- /dev/null +++ b/mixly/boards/default_src/python/blocks/control.js @@ -0,0 +1,1057 @@ +import * as Blockly from 'blockly/core'; + +const LOOPS_HUE = 120; + +export const controls_main = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_NAME_MAIN); + this.appendStatementInput('DO') + .appendField(''); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_SETUP); + } +}; + +export const base_setup = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_SETUP); + this.appendStatementInput('DO') + .appendField(''); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_SETUP); + } +}; + +export const controls_delay = { + init: function () { + var UNIT = [ + [Blockly.Msg.MIXLY_mSecond, 'delay'], + [Blockly.Msg.MIXLY_uSecond, 'delayMicroseconds'] + ]; + this.setColour(LOOPS_HUE); + this.appendValueInput("DELAY_TIME", Number) + .appendField(Blockly.Msg.MIXLY_DELAY) + .appendField(new Blockly.FieldDropdown(UNIT), 'UNIT') + .setCheck(Number); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_CONTROL_DELAY); + this.setHelpUrl("https://mixly.readthedocs.io/zh_CN/latest/arduino/03.Control.html#id9"); + this.wiki = { + 'zh-hans': { + page: ['Arduino AVR', '控制', '延时'] + } + }; + } +}; + +export const controls_end_program = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_CONTROL_END_PROGRAM); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_CONTROL_END_TOOLTIP); + } +}; + +export const controls_if = { + /** + * Block for if/elseif/else condition. + * @this Blockly.Block + */ + init: function () { + //this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL); + this.setColour(LOOPS_HUE); + this.appendValueInput('IF0') + .setCheck([Boolean, Number]) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendStatementInput('DO0') + .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setHelpUrl("https://mixly.readthedocs.io/zh_CN/latest/arduino/03.Control.html#if"); + this.setMutator(new Blockly.icons.MutatorIcon(['controls_if_elseif', + 'controls_if_else'], this)); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + if (!thisBlock.elseifCount_ && !thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_1; + } else if (!thisBlock.elseifCount_ && thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_2; + } else if (thisBlock.elseifCount_ && !thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_3; + } else if (thisBlock.elseifCount_ && thisBlock.elseCount_) { + return Blockly.Msg.CONTROLS_IF_TOOLTIP_4; + } + return ''; + }); + this.elseifCount_ = 0; + this.elseCount_ = 0; + }, + /** + * Create XML to represent the number of else-if and else inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + if (!this.elseifCount_ && !this.elseCount_) { + return null; + } + var container = document.createElement('mutation'); + if (this.elseifCount_) { + container.setAttribute('elseif', this.elseifCount_); + } + if (this.elseCount_) { + container.setAttribute('else', 1); + } + return container; + }, + /** + * Parse XML to restore the else-if and else inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var containerBlock = this; + var valueConnections = []; + var statementConnections = []; + // var elseStatementConnection = null; + if (this.elseCount_) { + // if (containerBlock.getInputTargetBlock('ELSE') && containerBlock.getInputTargetBlock('ELSE').previousConnection) + // elseStatementConnection = containerBlock.getInputTargetBlock('ELSE').previousConnection; + this.removeInput('ELSE'); + } + for (var i = this.elseifCount_; i > 0; i--) { + if (containerBlock.getInputTargetBlock('IF' + i) && containerBlock.getInputTargetBlock('IF' + i).previousConnection) + valueConnections[i] = (containerBlock.getInputTargetBlock('IF' + i).previousConnection); + else + valueConnections[i] = null; + this.removeInput('IF' + i); + if (containerBlock.getInputTargetBlock('DO' + i) && containerBlock.getInputTargetBlock('DO' + i).previousConnection) + statementConnections[i] = (containerBlock.getInputTargetBlock('DO' + i).previousConnection); + else + statementConnections[i] = null; + this.removeInput('DO' + i); + } + this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10); + this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10); + //this.compose(containerBlock); + for (var i = 1; i <= this.elseifCount_; i++) { + this.appendValueInput('IF' + i) + .setCheck([Boolean, Number]) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF); + this.appendStatementInput('DO' + i) + .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN); + } + if (this.elseCount_) { + this.appendStatementInput('ELSE') + .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE); + } + for (var i = valueConnections.length - 2; i > 0; i--) { + if (valueConnections[i]) + valueConnections[i].reconnect(this, 'IF' + i); + } + for (var i = statementConnections.length - 2; i > 0; i--) { + if (statementConnections[i]) + statementConnections[i].reconnect(this, 'DO' + i); + } + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = workspace.newBlock('controls_if_if'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 1; i <= this.elseifCount_; i++) { + var elseifBlock = workspace.newBlock('controls_if_elseif'); + elseifBlock.initSvg(); + connection.connect(elseifBlock.previousConnection); + connection = elseifBlock.nextConnection; + } + if (this.elseCount_) { + var elseBlock = workspace.newBlock('controls_if_else'); + elseBlock.initSvg(); + connection.connect(elseBlock.previousConnection); + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + // Disconnect the else input blocks and remove the inputs. + if (this.elseCount_) { + this.removeInput('ELSE'); + } + this.elseCount_ = 0; + // Disconnect all the elseif input blocks and remove the inputs. + for (var i = this.elseifCount_; i > 0; i--) { + this.removeInput('IF' + i); + this.removeInput('DO' + i); + } + this.elseifCount_ = 0; + // Rebuild the block's optional inputs. + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + var valueConnections = [null]; + var statementConnections = [null]; + var elseStatementConnection = null; + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_if_elseif': + this.elseifCount_++; + valueConnections.push(clauseBlock.valueConnection_); + statementConnections.push(clauseBlock.statementConnection_); + break; + case 'controls_if_else': + this.elseCount_++; + elseStatementConnection = clauseBlock.statementConnection_; + break; + default: + throw Error('Unknown block type: ' + clauseBlock.type); + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + + this.updateShape_(); + // Reconnect any child blocks. + this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); + + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 1; + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_if_elseif': + var inputIf = this.getInput('IF' + i); + var inputDo = this.getInput('DO' + i); + clauseBlock.valueConnection_ = + inputIf && inputIf.connection.targetConnection; + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + i++; + break; + case 'controls_if_else': + var inputDo = this.getInput('ELSE'); + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + break; + default: + throw 'Unknown block type.'; + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + }, + /** + * Reconstructs the block with all child blocks attached. + */ + rebuildShape_: function () { + var valueConnections = [null]; + var statementConnections = [null]; + var elseStatementConnection = null; + + if (this.getInput('ELSE')) { + elseStatementConnection = this.getInput('ELSE').connection.targetConnection; + } + var i = 1; + while (this.getInput('IF' + i)) { + var inputIf = this.getInput('IF' + i); + var inputDo = this.getInput('DO' + i); + console.log(inputIf.connection.targetConnection); + valueConnections.push(inputIf.connection.targetConnection); + statementConnections.push(inputDo.connection.targetConnection); + i++; + } + this.updateShape_(); + this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); + }, + /** + * Modify this block to have the correct number of inputs. + * @this Blockly.Block + * @private + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('ELSE')) { + this.removeInput('ELSE'); + } + var i = 1; + while (this.getInput('IF' + i)) { + this.removeInput('IF' + i); + this.removeInput('DO' + i); + i++; + } + // Rebuild block. + for (var i = 1; i <= this.elseifCount_; i++) { + this.appendValueInput('IF' + i) + .setCheck([Number, Boolean]) + .appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSEIF']); + this.appendStatementInput('DO' + i) + .appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']); + } + if (this.elseCount_) { + this.appendStatementInput('ELSE') + .appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSE']); + } + }, + /** + * Reconnects child blocks. + * @param {!Array} valueConnections List of value + * connectsions for if input. + * @param {!Array} statementConnections List of + * statement connections for do input. + * @param {?Blockly.RenderedConnection} elseStatementConnection Statement + * connection for else input. + */ + reconnectChildBlocks_: function (valueConnections, statementConnections, + elseStatementConnection) { + for (var i = 1; i <= this.elseifCount_; i++) { + valueConnections[i] && valueConnections[i].reconnect(this, 'IF' + i); + statementConnections[i] && statementConnections[i].reconnect(this, 'DO' + i); + } + elseStatementConnection && elseStatementConnection.reconnect(this, 'ELSE'); + } +}; + + +export const controls_range = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput('FROM') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PYTHON_RANGE) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_FROM); + this.appendValueInput('TO') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_TO); + this.appendValueInput('STEP') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.PYTHON_RANGE_STEP); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_CONTROLS_RANGE_TOOLTIP); + } +}; + + +export const controls_forEach = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput('LIST') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM) + // .appendField(new Blockly.FieldTextInput('i'), 'VAR'); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(function () { + return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('“%1”', ''); + }); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const controls_whileUntil = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput('BOOL') + .setCheck([Boolean, Number]) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_CURRENT) + .appendField(new Blockly.FieldDropdown(this.OPERATORS), 'MODE') + // this.appendDummyInput() + // .appendField(Blockly.Msg.CONTROLS_WHILE_SHI); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_TITLE_REPEAT + Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('MODE'); + var TOOLTIPS = { + 'WHILE': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE, + 'UNTIL': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL + }; + return TOOLTIPS[op]; + }); + } +}; + +export const controls_try_finally = { + /** + * Block for if/elseif/else condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_TRY); + this.appendStatementInput('try'); + this.appendValueInput('IF1') + .appendField(Blockly.Msg.MIXLY_PYTHON_EXCEPT); + this.appendStatementInput('DO1') + .appendField(''); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['controls_except', 'controls_finally'], this)); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_CONTROL_TRY_TOOLTIP); + this.elseifCount_ = 1; + this.elseCount_ = 0; + }, + /** + * Create XML to represent the number of else-if and else inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + if (!this.elseifCount_ && !this.elseCount_) { + return null; + } + var container = document.createElement('mutation'); + if (this.elseifCount_) { + container.setAttribute('elseif', this.elseifCount_); + } + if (this.elseCount_) { + container.setAttribute('else', 1); + } + return container; + }, + /** + * Parse XML to restore the else-if and else inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var containerBlock = this; + var valueConnections = []; + var statementConnections = []; + // var elseStatementConnection = null; + if (this.elseCount_) { + // if (containerBlock.getInputTargetBlock('ELSE') && containerBlock.getInputTargetBlock('ELSE').previousConnection) + // elseStatementConnection = containerBlock.getInputTargetBlock('ELSE').previousConnection; + this.removeInput('ELSE'); + } + for (var i = this.elseifCount_; i > 0; i--) { + if (containerBlock.getInputTargetBlock('IF' + i) && containerBlock.getInputTargetBlock('IF' + i).previousConnection) + valueConnections[i] = (containerBlock.getInputTargetBlock('IF' + i).previousConnection); + else + valueConnections[i] = null; + this.removeInput('IF' + i); + if (containerBlock.getInputTargetBlock('DO' + i) && containerBlock.getInputTargetBlock('DO' + i).previousConnection) + statementConnections[i] = (containerBlock.getInputTargetBlock('DO' + i).previousConnection); + else + statementConnections[i] = null; + this.removeInput('DO' + i); + } + this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10); + this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10); + //this.compose(containerBlock); + for (var i = 1; i <= this.elseifCount_; i++) { + this.appendValueInput('IF' + i) + .setCheck([Boolean, Number]) + .appendField(Blockly.Msg.MIXLY_PYTHON_EXCEPT); + this.appendStatementInput('DO' + i) + .appendField(""); + } + if (this.elseCount_) { + this.appendStatementInput('ELSE') + .appendField(Blockly.Msg.MIXLY_PYTHON_FINALLY); + } + for (var i = valueConnections.length - 2; i > 0; i--) { + if (valueConnections[i]) + valueConnections[i].reconnect(this, 'IF' + i); + } + for (var i = statementConnections.length - 2; i > 0; i--) { + if (statementConnections[i]) + statementConnections[i].reconnect(this, 'DO' + i); + } + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = workspace.newBlock('controls_try'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 1; i <= this.elseifCount_; i++) { + var elseifBlock = workspace.newBlock('controls_except'); + elseifBlock.initSvg(); + connection.connect(elseifBlock.previousConnection); + connection = elseifBlock.nextConnection; + } + if (this.elseCount_) { + var elseBlock = workspace.newBlock('controls_finally'); + elseBlock.initSvg(); + connection.connect(elseBlock.previousConnection); + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + // Disconnect the else input blocks and remove the inputs. + if (this.elseCount_) { + this.removeInput('ELSE'); + } + this.elseCount_ = 0; + // Disconnect all the elseif input blocks and remove the inputs. + for (var i = this.elseifCount_; i > 0; i--) { + this.removeInput('IF' + i); + this.removeInput('DO' + i); + } + this.elseifCount_ = 0; + // Rebuild the block's optional inputs. + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + var valueConnections = [null]; + var statementConnections = [null]; + var elseStatementConnection = null; + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_except': + this.elseifCount_++; + valueConnections.push(clauseBlock.valueConnection_); + statementConnections.push(clauseBlock.statementConnection_); + break; + case 'controls_finally': + this.elseCount_++; + elseStatementConnection = clauseBlock.statementConnection_; + break; + default: + throw Error('Unknown block type: ' + clauseBlock.type); + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + + this.updateShape_(); + // Reconnect any child blocks. + this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); + + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var clauseBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 1; + while (clauseBlock) { + switch (clauseBlock.type) { + case 'controls_except': + var inputIf = this.getInput('IF' + i); + var inputDo = this.getInput('DO' + i); + clauseBlock.valueConnection_ = + inputIf && inputIf.connection.targetConnection; + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + i++; + break; + case 'controls_finally': + var inputDo = this.getInput('ELSE'); + clauseBlock.statementConnection_ = + inputDo && inputDo.connection.targetConnection; + break; + default: + throw 'Unknown block type.'; + } + clauseBlock = clauseBlock.nextConnection && + clauseBlock.nextConnection.targetBlock(); + } + }, + /** + * Reconstructs the block with all child blocks attached. + */ + rebuildShape_: function () { + var valueConnections = [null]; + var statementConnections = [null]; + var elseStatementConnection = null; + + if (this.getInput('ELSE')) { + elseStatementConnection = this.getInput('ELSE').connection.targetConnection; + } + var i = 1; + while (this.getInput('IF' + i)) { + var inputIf = this.getInput('IF' + i); + var inputDo = this.getInput('DO' + i); + console.log(inputIf.connection.targetConnection); + valueConnections.push(inputIf.connection.targetConnection); + statementConnections.push(inputDo.connection.targetConnection); + i++; + } + this.updateShape_(); + this.reconnectChildBlocks_(valueConnections, statementConnections, elseStatementConnection); + }, + /** + * Modify this block to have the correct number of inputs. + * @this Blockly.Block + * @private + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('ELSE')) { + this.removeInput('ELSE'); + } + var i = 1; + while (this.getInput('IF' + i)) { + this.removeInput('IF' + i); + this.removeInput('DO' + i); + i++; + } + // Rebuild block. + for (var i = 1; i <= this.elseifCount_; i++) { + this.appendValueInput('IF' + i) + .setCheck([Number, Boolean]) + .appendField(Blockly.Msg.MIXLY_PYTHON_EXCEPT); + this.appendStatementInput('DO' + i) + .appendField(''); + } + if (this.elseCount_) { + this.appendStatementInput('ELSE') + .appendField(Blockly.Msg.MIXLY_PYTHON_FINALLY); + } + }, + /** + * Reconnects child blocks. + * @param {!Array} valueConnections List of value + * connectsions for if input. + * @param {!Array} statementConnections List of + * statement connections for do input. + * @param {?Blockly.RenderedConnection} elseStatementConnection Statement + * connection for else input. + */ + reconnectChildBlocks_: function (valueConnections, statementConnections, + elseStatementConnection) { + for (var i = 1; i <= this.elseifCount_; i++) { + valueConnections[i] && valueConnections[i].reconnect(this, 'IF' + i); + statementConnections[i] && statementConnections[i].reconnect(this, 'DO' + i); + } + elseStatementConnection && elseStatementConnection.reconnect(this, 'ELSE'); + } +}; + +export const controls_flow_statements = { + init: function () { + this.setColour(LOOPS_HUE); + var dropdown = new Blockly.FieldDropdown(this.OPERATORS); + this.appendDummyInput() + .appendField(dropdown, 'FLOW') + .appendField(Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_INPUT_OFLOOP); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_CONTROLS_FLOW_STATEMENTS_TOOLTIP); + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('FLOW'); + var TOOLTIPS = { + 'BREAK': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK, + 'CONTINUE': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE + }; + return TOOLTIPS[op]; + }); + }, + onchange: function () { + if (!this.workspace) { + // Block has been deleted. + return; + } + var legal = false; + // Is the block nested in a control statement? + var block = this; + do { + if (block.type == 'controls_repeat' || + block.type == 'controls_for' || + block.type == 'controls_forEach' || + block.type == 'controls_repeat_ext' || + block.type == 'controls_whileUntil' || + block.type == 'do_while') { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_WARNING); + } + } +}; + + +export const controls_for = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_WITH) + .appendField(new Blockly.FieldTextInput('i'), 'VAR'); + this.appendValueInput('FROM') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_FROM); + this.appendValueInput('TO') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_TO); + this.appendValueInput('STEP') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEP); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1', + thisBlock.getFieldValue('VAR')); + }); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const controls_for_range = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_WITH) + .appendField(new Blockly.FieldTextInput('i'), 'VAR'); + this.appendValueInput('FROM') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_FROM); + this.appendValueInput('TO') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_TO); + this.appendValueInput('STEP') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.MIXLY_STEP); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_DO); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + return Blockly.Msg.MIXLY_PYTHON_CONTROLS_FOR_RANGE_TOOLTIP.replace('%1', + thisBlock.getFieldValue('VAR')); + }); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + + +controls_whileUntil.OPERATORS = [ + [Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'], + [Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, 'UNTIL'] +]; + + + +controls_flow_statements.OPERATORS = [ + [Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'], + [Blockly.Msg.LANG_CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE, 'CONTINUE'] +]; + + + +export const controls_if_if = { + /** + * Mutator block for if container. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP); + this.contextMenu = false; + } +}; + +export const controls_if_elseif = { + /** + * Mutator bolck for else-if condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP); + this.contextMenu = false; + } +}; + +export const controls_if_else = { + /** + * Mutator block for else condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP); + this.contextMenu = false; + } +}; + + + +export const controls_try = { + /** + * Mutator block for if container. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField('try'); + this.appendStatementInput('STACK'); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.contextMenu = false; + } +}; + +export const controls_except = { + /** + * Mutator bolck for else-if condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_EXCEPT); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.contextMenu = false; + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_CONTROL_EXCEPT_TOOLTIP); + } +}; + +export const controls_finally = { + /** + * Mutator block for else condition. + * @this Blockly.Block + */ + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_FINALLY); + this.setPreviousStatement(true); + this.contextMenu = false; + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_CONTROL_FINALLY_TOOLTIP); + } +}; + + + +export const controls_repeat_ext = { + /** + * Block for repeat n times (external number). + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "message0": Blockly.Msg.CONTROLS_REPEAT_TITLE, + "args0": [ + { + "type": "input_value", + "name": "TIMES", + // "check": "Number" + } + ], + "previousStatement": null, + "nextStatement": null, + "colour": LOOPS_HUE, + "tooltip": Blockly.Msg.CONTROLS_REPEAT_TOOLTIP, + "helpUrl": Blockly.Msg.CONTROLS_REPEAT_HELPURL + }); + this.appendStatementInput('DO'); + } +}; + + + +export const controls_lambda = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput('BOOL') + .appendField('lambda') + //.appendField(new Blockly.FieldDropdown(this.OPERATORS), 'MODE'); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.MIXLY_STAT); + this.setOutput(true); + // this.setNextStatement(true); + } +}; + +export const controls_pass = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_PASS); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_CONTROLS_PASS_TOOLTIP); + } +}; + +export const controls_thread = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_CONTROLS_THREAD_START) + this.appendValueInput('callback') + .appendField(Blockly.Msg.MIXLY_PYTHON_CONTROLS_THREAD_USE) + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_PARAMS); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_CONTROLS_THREAD_TOOLTIP); + } +}; + +//do-while循环 +export const do_while = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT + Blockly.Msg.MIXLY_DO); + this.appendStatementInput("input_data") + .setCheck(null) + this.appendValueInput("select_data") + .setCheck(null) + .appendField(Blockly.Msg.CONTROLS_OPERATOR_UNTIL) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_WHILE, "true"], [Blockly.Msg.LANG_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, "false"]]), "type"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setColour(LOOPS_HUE); + this.setTooltip("do-while loop"); + this.setHelpUrl(""); + } +}; + +export const garbage_collection = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_OP_GARBAGE_COLLECT); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + + +export const get_mem_alloc = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_MEM_ALLOC); + this.setOutput(true) + } +}; + +export const get_mem_free = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_MEM_FREE); + this.setOutput(true) + } +}; + +export const get_unique_identifier = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET + Blockly.Msg.MIXLY_DEVICE + 'ID'); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_GET_UNIQUE_IDEN); + } +}; + +// export const base_type = controls_type; +// export const controls_TypeLists = controls_typeLists; + +export const datetime_fromtimestamp = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_RTC_TIMESTAMP); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TIMESTAMP_TO_DATA); + this.setInputsInline(true); + this.setOutput(true, Number); + } +}; + + +export const gene_unique_identifier = { + init: function () { + this.setColour(LOOPS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_GET_UNIQUE_IDEN); + this.setOutput(true) + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/dicts.js b/mixly/boards/default_src/python/blocks/dicts.js new file mode 100644 index 00000000..78862929 --- /dev/null +++ b/mixly/boards/default_src/python/blocks/dicts.js @@ -0,0 +1,773 @@ +/** + * @license + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Dictionary blocks for Blockly. + * @author acbart@vt.edu (Austin Cory Bart) + */ +import * as Blockly from 'blockly/core'; + +const DICTS_HUE = 345; + +export const dicts_create_with = { + + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + + init: function () { + this.setColour(DICTS_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('mydict'), 'VAR') + .appendField(new Blockly.FieldLabel(Blockly.Msg.DICTS_CREATE_WITH_INPUT_WITH), 'TIP') + this.itemCount_ = 3; + this.updateShape_(); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['dicts_create_with_item'], this)); + this.setTooltip(Blockly.Msg.DICTS_CREATE_WITH_TOOLTIP); + }, + + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('dicts_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('dicts_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } + + var keyNames = []; + for (var i = 0; this.getInput('ADD' + i); i++) { + //this.getInput('VALUE' + i).removeField("KEY"+i); + keyNames.push(this.getFieldValue("KEY" + i)) + this.removeInput('ADD' + i); + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.getField('TIP').setValue(Blockly.Msg.DICTS_CREATE_EMPTY_TITLE); + } else { + this.getField('TIP').setValue(Blockly.Msg.DICTS_CREATE_WITH_INPUT_WITH); + for (var i = 0; i < this.itemCount_; i++) { + this.appendValueInput('ADD' + i) + .setCheck(null) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField( + new Blockly.FieldTextInput( + keyNames.length > i + ? keyNames[i] + : (i == 0 ? '"key"' : '"key' + (i + 1) + '"')), + 'KEY' + i) + .appendField(":") + } + } + }, getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + + + +export const dicts_create_with_container = { + + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.DICTS_CREATE_WITH_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const dicts_create_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.DICTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.DICTS_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const dicts_keys = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput("") + .appendField(Blockly.Msg.DICT_KEYS); + this.setTooltip(Blockly.Msg.DICTS_KEYS_TOOLTIP); + this.setOutput(true, 'List'); + } +}; + +export const dicts_get = { + init: function () { + this.setColour(DICTS_HUE); + // this.appendDummyInput("") + + // .appendField(Blockly.Msg.DICTS_GET_FROM_DICTS) + + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendValueInput('KEY') + .appendField(Blockly.Msg.DICTS_GET_IN) + this.appendDummyInput("") + // .appendField(new Blockly.FieldTextInput('"key"'), 'KEY') + .appendField(Blockly.Msg.DICTS_ADD_VALUE); + + this.setOutput(true); + this.setTooltip(Blockly.Msg.DICTS_GET_TOOLTIP); + } +}; + +export const dicts_get_default = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendValueInput('KEY') + .appendField(Blockly.Msg.DICTS_GET_IN) + this.appendDummyInput("") + .appendField(Blockly.Msg.DICTS_ADD_VALUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.DICTS_DEFAULT_VALUE); + this.setOutput(true); + this.setTooltip(Blockly.Msg.DICTS_GET_DEFAULT_TOOLTIP); + } +}; + +export const dicts_add_or_change = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + this.appendValueInput('KEY') + .appendField(Blockly.Msg.DICTS_ADD) + // .appendField(new Blockly.FieldTextInput('"key"'), 'KEY') + this.appendDummyInput() + this.appendValueInput('VAR') + .appendField(Blockly.Msg.DICTS_ADD_VALUE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.DICTS_ADD_OR_CHANGE_TOOLTIP); + } +}; + + +export const dicts_delete = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + this.appendValueInput('KEY') + .appendField(Blockly.Msg.DICTS_DELETE_IN) + this.appendDummyInput("") + // .appendField(new Blockly.FieldTextInput('"key"'), 'KEY') + .appendField(Blockly.Msg.DICTS_DELETE_VALUE); + + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.DICTS_DELETE_TOOLTIP); + } +}; + + +export const dicts_update = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT2') + .setCheck('Dict') + .appendField(Blockly.Msg.MAKE_DICT) + this.appendValueInput('DICT') + .setCheck('Dict') + .appendField(Blockly.Msg.DICT_UPDATE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MID); + this.setTooltip(Blockly.Msg.DICTS_UPDATE_TOOLTIP); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const dicts_clear = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput("") + .appendField(Blockly.Msg.DICT_CLEAR); + this.setTooltip(Blockly.Msg.DICTS_CLEAR_TOOLTIP); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const dicts_items = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput("") + + .appendField(Blockly.Msg.DICT_ITEMS); + this.setTooltip(Blockly.Msg.DICTS_ITEMS_TOOLTIP); + this.setOutput(true, 'List'); + } +}; + +export const dicts_values = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput("") + + .appendField(Blockly.Msg.DICT_VALUES); + this.setTooltip(Blockly.Msg.DICTS_VALUES_TOOLTIP); + this.setOutput(true, 'List'); + } +}; + +export const dicts_length = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LENGTH) + + this.setTooltip(Blockly.Msg.DICT_LENGTH_TOOLTIP); + this.setOutput(true, Number); + } +}; + +export const dicts_deldict = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput("") + + .appendField(Blockly.Msg.DICT_DELDICT); + this.setTooltip(Blockly.Msg.DICTS_DEL_TOOLTIP); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const dicts_add_change_del = { + /** + * Block for getting sublist. + * @this Blockly.Block + */ + init: function () { + + this['MODE'] = [ + [Blockly.Msg.DICTS_ADD_OR_CHANGE, 'INSERT'], + [Blockly.Msg.MIXLY_MICROBIT_JS_DELETE_VAR, 'DELETE'] + ]; + this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL); + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput('AT2') + this.appendValueInput('KEY') + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + // .appendField(new Blockly.FieldTextInput('"key"'), 'KEY') + .appendField(Blockly.Msg.DICTS_ADD_VALUE); + this.updateAt_(true); + this.setInputsInline(true); + this.setOutput(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + var b = this; + this.setTooltip(function () { + var e = b.getFieldValue("WHERE"), + d = ""; + switch (e) { + case "INSERT": + d = Blockly.Msg.DICTS_ADD_TOOLTIP; + break; + case "DELETE": + d = Blockly.Msg.DICTS_DELETE_TOOLTIP; + break; + } + //if ("FROM_START" == e || "FROM_END" == e) d += " " + Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP.replace("%1", ONE_BASED_INDEXING ? "#1": "#0"); + return d + }) + + }, + /** + * Create XML to represent whether there are 'AT' inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + var isAt = this.getInput('AT2').type == Blockly.INPUT_VALUE; + container.setAttribute('at2', isAt); + return container; + }, + /** + * Parse XML to restore the 'AT' inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var isAt = (xmlElement.getAttribute('at2') == 'true'); + this.updateAt_(isAt); + }, + /** + * Create or delete an input for a numeric index. + * This block has two such inputs, independant of each other. + * @param {number} n Specify first or second input (1 or 2). + * @param {boolean} isAt True if the input should exist. + * @private + * @this Blockly.Block + */ + updateAt_: function (isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' inputs. + this.removeInput('AT2'); + this.removeInput('ORDINAL', true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT2').setCheck(Number); + } else { + this.appendDummyInput('AT2'); + } + var menu = new Blockly.FieldDropdown(this['MODE'], + function (value) { + var newAt = (value == 'INSERT'); + // The 'isAt' variable is available due to this function being a + // closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt_(newAt); + // This menu has been destroyed and replaced. + // Update the replacement. + block.setFieldValue(value, 'WHERE'); + return null; + } + return undefined; + }); + + this.getInput('AT2') + .appendField(menu, 'WHERE'); + + // this.moveInputBefore('AT2','LIST'); + } +}; + +export const dicts_pop = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict') + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_DICT_POP) + this.appendValueInput('KEY') + this.appendDummyInput("") + // .appendField(new Blockly.FieldTextInput('"key"'), 'KEY') + .appendField(Blockly.Msg.DICTS_ADD_VALUE); + this.setTooltip(Blockly.Msg.DICT_POP_TOOLTIP); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const dicts_setdefault = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict'); + this.appendValueInput('KEY') + .appendField(Blockly.Msg.DICTS_SET_DEFAULT) + this.appendDummyInput("") + // .appendField(new Blockly.FieldTextInput('"key"'), 'KEY') + .appendField(Blockly.Msg.DICTS_DEFAULT_VALUE); + this.appendValueInput('VAR') + + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.DICTS_SETDEFAULT_TOOLTIP); + } +}; + +export const dicts_create_with_noreturn = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(DICTS_HUE); + this.appendDummyInput("") + // .appendField(new Blockly.FieldTextInput('mydict'), 'VAR') + .appendField(new Blockly.FieldLabel(Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT), 'TIP') + .appendField(' ') + this.itemCount_ = 3; + this.updateShape_(); + this.setOutput(true, "Dict") + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setMutator(new Blockly.icons.MutatorIcon(['dicts_create_with_item'], this)); + this.setTooltip(Blockly.Msg.DICTS_CREATE_WITH_TOOLTIP); + }, + + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('dicts_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('dicts_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } + + var keyNames = []; + for (var i = 0; this.getInput('ADD' + i); i++) { + //this.getInput('VALUE' + i).removeField("KEY"+i); + keyNames.push(this.getFieldValue("KEY" + i)) + this.removeInput('ADD' + i); + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.getField('TIP').setValue(Blockly.Msg.LOGIC_NULL + Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT); + } else { + this.getField('TIP').setValue(Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT); + for (var i = 0; i < this.itemCount_; i++) { + this.appendValueInput('ADD' + i) + .setCheck(null) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField( + new Blockly.FieldTextInput( + keyNames.length > i + ? keyNames[i] + : (i == 0 ? '"key"' : '"key' + (i + 1) + '"')), + 'KEY' + i) + .appendField(":") + } + + } + }, getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const dicts_todict = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_TODICT); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TODICT); + } +}; + +export const dicts_to_json = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_TO_JSON); + this.setTooltip(Blockly.Msg.MIXLY_TO_JSON_TOOLTIP); + this.setOutput(true); + } +}; + +export const json_to_dicts = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('VAR'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_CONVERT_TO_JSON); + this.setTooltip(Blockly.Msg.MIXLY_CONVERT_TO_JSON_TOOLTIP); + this.setOutput(true); + } +}; + +export const dicts_to_to ={ + init:function(){ + this.setColour(DICTS_HUE); + this.appendValueInput('DICT') + .setCheck('Dict'); + this.appendValueInput('VAR1') + .appendField('key1'); + this.appendValueInput('VAR2') + .appendField('index'); + this.appendValueInput('VAR3') + .appendField('key2'); + this.appendValueInput('VAR4') + .appendField('key3'); + this.setInputsInline(true) + this.setTooltip(Blockly.Msg.MIXLY_CONVERT_TO_JSON_TOOLTIP); + this.setOutput(true); + } +} + +export const dicts_to_json2 = { + init: function () { + this.setColour(DICTS_HUE); + this.appendValueInput('DICT'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_TO_JSON); + this.setTooltip(Blockly.Msg.MIXLY_TO_JSON_TOOLTIP); + this.setOutput(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/html.js b/mixly/boards/default_src/python/blocks/html.js new file mode 100644 index 00000000..2da4d3d4 --- /dev/null +++ b/mixly/boards/default_src/python/blocks/html.js @@ -0,0 +1,177 @@ +import * as Blockly from 'blockly/core'; + +const HTML_HUE = '#1ec1e4'; + +export const html_document = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_DOCUMENT); + this.appendStatementInput('HEAD') + .appendField(Blockly.Msg.HTML_HEAD); + this.appendStatementInput('BODY') + .appendField(Blockly.Msg.HTML_BODY); + this.setOutput(true); + } +}; + +export const html_title = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_LEVEL) + .appendField(new Blockly.FieldDropdown([["1", "1"], ["2", "2"], ["3", "3"], ["4", "4"], ["5", "5"], ["6", "6"]]), 'LEVEL'); + this.appendStatementInput('DO') + .appendField(''); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const html_head_body = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.HTML_HEAD, "head"], + [Blockly.Msg.HTML_BODY, "body"] + ]), 'LEVEL'); + this.appendStatementInput('DO') + .appendField(''); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const html_content = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.HTML_P, "p"], + [Blockly.Msg.HTML_SPAN, "span"], + [Blockly.Msg.HTML_FORM, "form"], + [Blockly.Msg.HTML_TABLE, "table"], + [Blockly.Msg.HTML_LINE, "tr"], + [Blockly.Msg.HTML_CELL, "td"], + [Blockly.Msg.HTML_OL, "ol"], + [Blockly.Msg.HTML_UL, "ul"], + [Blockly.Msg.HTML_LI, "li"] + ]), 'LEVEL') + // this.appendValueInput('style') + // .appendField(Blockly.Msg.MIXLY_AIP_ATTR) + // .setAlign(Blockly.inputs.Align.RIGHT); + this.appendStatementInput('DO') + .appendField(''); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const html_content_more = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField('<') + .appendField(new Blockly.FieldTextInput('tag'), "LEVEL") + .appendField('>') + this.appendValueInput('style') + .appendField(Blockly.Msg.MIXLY_AIP_ATTR) + .setAlign(Blockly.inputs.Align.RIGHT); + this.appendStatementInput('DO') + .appendField(''); + this.setInputsInline(false); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const html_style = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_STYLE) + this.appendStatementInput('STYLE'); + this.setOutput(true); + } +}; + +export const html_form = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_FORM_CONTENT) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.HTML_TEXT, "text"], + [Blockly.Msg.HTML_EMAIL, "email"], + [Blockly.Msg.HTML_NUMBER, "number"], + [Blockly.Msg.HTML_PASSWORD, "password"], + [Blockly.Msg.HTML_CHECKBOX, "checkbox"], + [Blockly.Msg.HTML_RADIOBUTTON, "radiobutton"], + [Blockly.Msg.HTML_BUTTON, "button"], + [Blockly.Msg.HTML_COLOUR, "colour"], + [Blockly.Msg.HTML_DATE, "date"], + [Blockly.Msg.HTML_LOCALTIME, "local time"], + [Blockly.Msg.HTML_FILE, "file"], + [Blockly.Msg.HTML_HIDDEN, "hidden"], + [Blockly.Msg.HTML_IMAGE, "image"], + [Blockly.Msg.HTML_MONTH, "month"], + [Blockly.Msg.HTML_RANGE, "range"], + [Blockly.Msg.HTML_RESET, "reset"], + [Blockly.Msg.HTML_SEARCH, "search"], + [Blockly.Msg.HTML_SUBMIT, "submit"], + [Blockly.Msg.HTML_TELEPHONENUMBER, "telephone number"], + [Blockly.Msg.HTML_TIME, "time"], + [Blockly.Msg.HTML_URL, "url"], + [Blockly.Msg.HTML_WEEK, "week"] + ]), 'LEVEL') + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_NAME) + .appendField(new Blockly.FieldTextInput('car'), "NAME") + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_VALUE) + .appendField(new Blockly.FieldTextInput('go'), "VALUE") + this.appendValueInput('style') + .appendField(Blockly.Msg.MIXLY_AIP_ATTR) + .setAlign(Blockly.inputs.Align.RIGHT); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const html_style_content = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput('property'), "KEY") + .appendField(':') + .appendField(new Blockly.FieldTextInput('value'), "VALUE") + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const html_style_color = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput('property'), "KEY") + .appendField(':') + .appendField(new Blockly.FieldColour("#ff0000"), "RGB_LED_COLOR"); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const html_text = { + init: function () { + this.setColour(HTML_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.HTML_TEXT) + .appendField(new Blockly.FieldTextInput('text'), "TEXT"); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/lists.js b/mixly/boards/default_src/python/blocks/lists.js new file mode 100644 index 00000000..3e69e6bc --- /dev/null +++ b/mixly/boards/default_src/python/blocks/lists.js @@ -0,0 +1,840 @@ +import * as Blockly from 'blockly/core'; + +const LISTS_HUE = 260; //'#70b234'//260; + +export const lists_get_index = { + init: function () { + this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL); + this.setColour(LISTS_HUE); + this.appendValueInput("LIST") + this.appendValueInput("AT") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + " " + Blockly.Msg.LISTS_GET_INDEX_FROM_START) + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_CHARAT_TAIL); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM); + } +} + + +export const lists_get_sublist = { + /** + * Block for getting sublist. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL); + this.setColour(LISTS_HUE); + this.appendValueInput('LIST') + this.appendDummyInput('') + this.appendValueInput('AT1') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + " " + Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendValueInput('AT2') + .appendField(Blockly.Msg.TEXT_CHARAT_TAIL + " " + Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_CHARAT_TAIL); + this.setInputsInline(true); + this.setOutput(true, 'List'); + this.setTooltip(Blockly.Msg.PYTHON_LISTS_GET_SUBLIST_TOOLTIP); + } +} + +export const lists_2d_get_data_with_col_row = { + init: function () { + this.appendValueInput("LIST") + .setCheck(null); + this.appendValueInput("row") + .setCheck(null) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + " " + Blockly.Msg.DATAFRAME_RAW); + this.appendValueInput("col") + .setCheck(null) + .appendField(Blockly.Msg.DATAFRAME_COLUMN); + this.setInputsInline(true); + this.setOutput(true, null); + this.setColour(LISTS_HUE); + this.setTooltip(""); + this.setHelpUrl(""); + } +}; + +export const lists_2d_get_col_row_data = { + init: function () { + this.appendValueInput("LIST") + .setCheck(null); + this.appendValueInput("row_start") + .setCheck(null) + .appendField(Blockly.Msg.MIXLY_GET + " " + Blockly.Msg.DATAFRAME_RAW + " ["); + this.appendValueInput("row_end") + .setCheck(null) + .appendField(","); + this.appendValueInput("col_start") + .setCheck(null) + .appendField(") " + Blockly.Msg.DATAFRAME_COLUMN + " ["); + this.appendValueInput("col_end") + .setCheck(null) + .appendField(","); + this.appendDummyInput() + .appendField(") " + Blockly.Msg.DICTS_ADD_VALUE); + this.setInputsInline(true); + this.setOutput(true, 'List'); + this.setColour(LISTS_HUE); + this.setTooltip(""); + this.setHelpUrl(""); + } +}; + +export const lists_create_with = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(LISTS_HUE); + this.appendDummyInput("") + //don't need to specify the data type in Python + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'Array'], [Blockly.Msg.LANG_MATH_STRING, 'Array'], [Blockly.Msg.LANG_MATH_BOOLEAN, 'Array']]), 'TYPE') + // .appendField(' ') + .appendField(new Blockly.FieldTextInput('mylist'), 'VAR') + .appendField('[') + //.appendField(new Blockly.FieldTextInput('3',Blockly.FieldTextInput.math_number_validator), 'SIZE') + .appendField(']'); + this.itemCount_ = 3; + this.updateShape_(); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['lists_create_with_item'], this)); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_PYTHON_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('lists_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('lists_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.LISTS_CREATE_PYTHON_EMPTY_TITLE); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.blockpy_LISTS_CREATE_WITH_INPUT_WITH); + } + } + } + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + + +export const lists_create_with_text = { + init: function () { + this.setColour(LISTS_HUE); + this.appendDummyInput("") + //don't need to specify the data type in Python + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'Array']]), 'TYPE') + // .appendField(' ') + // .appendField(Blockly.Msg.blockpy_MIXLY_SPLITBYDOU) + .appendField(new Blockly.FieldTextInput('mylist'), 'VAR') + //.appendField(new Blockly.FieldTextInput('3',Blockly.FieldTextInput.math_number_validator), 'SIZE') + // .appendField(Blockly.Msg.MIXLY_MAKELISTFROM) + // .appendField(this.newQuote_(true)) + .appendField(' = [') + .appendField(new Blockly.FieldTextInput('0,0,0'), 'TEXT') + .appendField(']'); + // .appendField(this.newQuote_(false)) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_LISTS_CREATE_WITH_TEXT2); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +} + + +export const lists_create_with_container = { + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(LISTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const lists_create_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(LISTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + + +export const lists_set_index = { + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('LIST'); + this.appendValueInput('AT') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_LIST_ASSIGN_AT); + this.appendValueInput('TO') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_LIST_VALUE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.LANG_LISTS_SET_INDEX_TOOLTIP); + } +}; + +export const lists_append_extend = { + init: function () { + this.setColour(LISTS_HUE); + this['TYPE'] = [ + [Blockly.Msg.MIXLY_blockpy_set_add, 'append'], + [Blockly.Msg.MIXLY_MICROBIT_LIST_EXTEND, 'extend'] + ]; + + this.appendValueInput('LIST') + .setCheck('List') + this.appendValueInput('DATA') + .appendField(new Blockly.FieldDropdown(this['TYPE']), 'OP') + .appendField(Blockly.Msg.MIXLY_MICROBIT_LIST_A_ITEM) + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_LIST_TO_END); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'append': Blockly.Msg.MIXLY_TOOLTIP_LIST_APPEND, + 'extend': Blockly.Msg.LISTS_EXTEND_TOOLTIP + + }; + return TOOLTIPS[mode]; + }); + } + +}; + +export const lists_get_random_item = { + /** + * Block for get a random item from list. + * @this Blockly.Block + */ + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput("LIST"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + " " + Blockly.Msg.LISTS_GET_INDEX_RANDOM) + this.setTooltip(Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM); + this.setOutput(true); + } +}; + +export const lists_get_random_sublist = { + /** + * Block for get a random item from list. + * @this Blockly.Block + */ + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput("LIST"); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + Blockly.Msg.MIXLY_MICROBIT_RANDOM) + this.appendDummyInput() + .appendField(Blockly.Msg.LANG_LISTS_GET_INDEX2 + Blockly.Msg.LISTS_GET_RANDOM_SUBLIST) + this.setTooltip(Blockly.Msg.LISTS_GET_RANDOM_SUBLIST_TOOLTIP); + this.setOutput(true, 'List'); + } +}; + +export const lists_insert_value = { + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('LIST'); + this.appendValueInput('AT') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_LIST_INSERT_AT); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_LIST_VALUE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.LANG_LISTS_SET_INDEX_TOOLTIP); + this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT); + } +}; + +export const lists_reverse = { + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('VAR') + .setCheck('List') //this.appendDummyInput("") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_LIST_REVERSE) + //.appendField(new Blockly.FieldTextInput('mylist'), 'VAR'); + this.setTooltip(Blockly.Msg.LANG_LISTS_CLEAR_TOOLTIP); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; +export const lists_clear = { + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('VAR') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_CLEAR) + //.appendField(new Blockly.FieldTextInput('mylist'), 'VAR'); + this.setTooltip(Blockly.Msg.LANG_LISTS_REVERSE_TOOLTIP); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + + +export const lists_remove_at = { + init: function () { + this.setColour(LISTS_HUE); + this['TYPE'] = [ + [Blockly.Msg.SERIES_INDEX, 'del'], + [Blockly.Msg.MIXLY_MICROBIT_JS_I2C_VALUE, 'remove'] + ]; + this.appendValueInput('LIST') + .setCheck('List') + this.appendValueInput('DATA') + .appendField(Blockly.Msg.MIXLY_MIXPY_LISTS_REMOVE) + .appendField(new Blockly.FieldDropdown(this['TYPE']), 'OP') + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'del': Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_DELETE, + 'remove': Blockly.Msg.MIXLY_TOOLTIP_LIST_REMOVE + }; + return TOOLTIPS[mode]; + }); + } +}; +export const lists_pop = { + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('LIST'); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.MIXLY_MICROBIT_LIST_POP); + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_CHARAT_TAIL); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM); + } +}; + +export const lists_find = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MIXLY_LIST_INDEX, 'INDEX'], + [Blockly.Msg.MIXLY_LIST_COUNT, 'COUNT'] + ]; + this.setColour(LISTS_HUE); + this.appendValueInput('VAR') + .setCheck('List') + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.HTML_VALUE) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DE) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + //.appendField(new Blockly.FieldTextInput('mylist'), 'VAR') + this.setInputsInline(true); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'INDEX': Blockly.Msg.MIXLY_TOOLTIP_LIST_FIND_INDEX, + 'COUNT': Blockly.Msg.MIXLY_TOOLTIP_LIST_FIND_COUNT + + }; + return TOOLTIPS[mode]; + }); + } +}; +export const list_trig = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MIXLY_LIST_LEN, 'LEN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MAX, 'MAX'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MIN, 'MIN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE, 'AVERAGE'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN, 'MEDIAN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MODE, 'MODE'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV, 'STD_DEV'], + ]; + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(LISTS_HUE); + this.setOutput(true, Number); + this.appendValueInput('data') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'LEN': Blockly.Msg.LISTS_LENGTH_TOOLTIP, + 'SUM': Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM, + 'MAX': Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX, + 'MIN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN, + 'AVERAGE': Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE, + 'MEDIAN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN, + 'MODE': Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE, + 'STD_DEV': Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV + + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const lists_sort = { + /** + * Block for sorting a list. + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "args0": [ + { + "type": "input_value", + "name": "LIST", + "check": "List" + }, + { + "type": "field_dropdown", + "name": "TYPE", + "options": [ + [Blockly.Msg.LISTS_SORT_TYPE_NUMERIC, "NUMERIC"], + [Blockly.Msg.LISTS_SORT_TYPE_TEXT, "TEXT"], + [Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE, "IGNORE_CASE"] + ] + }, + { + "type": "field_dropdown", + "name": "DIRECTION", + "options": [ + [Blockly.Msg.LISTS_SORT_ORDER_ASCENDING, "1"], + [Blockly.Msg.LISTS_SORT_ORDER_DESCENDING, "-1"] + ] + }, + ], + "message0": Blockly.Msg.LISTS_SORT_TITLE, + "inputsInline": true, + "output": "List", + "colour": LISTS_HUE, + "tooltip": Blockly.Msg.LISTS_SORT_TOOLTIP, + "helpUrl": Blockly.Msg.LISTS_SORT_HELPURL + }); + } +}; + +export const lists_change_to = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, 'tuple'], + [Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, 'set'], + [Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD, 'array'] + ]; + this.setColour(LISTS_HUE); + this.appendValueInput('VAR') + .setCheck("List") + // .appendField(Blockly.Msg.blockpy_USE_LIST); + this.appendDummyInput("") + .appendField(Blockly.Msg.A_TO_B) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'tuple': Blockly.Msg.MIXLY_TOOLTIP_CONVERT_LIST_TO_TUPLE, + 'set': Blockly.Msg.MIXLY_TOOLTIP_CONVERT_LIST_TO_SET, + 'array': Blockly.Msg.MIXLY_TOOLTIP_CONVERT_LIST_TO_ARRAY + }; + return TOOLTIPS[mode]; + }); + + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const list_many_input = { + init: function () { + this.setColour(LISTS_HUE); + this.appendDummyInput("") + .appendField('[') + .appendField(new Blockly.FieldTextInput('0,0,0'), "CONTENT") + .appendField(']'); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const lists_create_with_noreturn = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(LISTS_HUE); + this.itemCount_ = 3; + this.updateShape_(); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, "List") + this.setMutator(new Blockly.icons.MutatorIcon(['lists_create_with_item'], this)); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_PYTHON_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('lists_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('lists_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.LISTS_CREATE_PYTHON_EMPTY_TITLE); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.blockpy_LISTS_CREATE_WITH_INPUT_WITH); + } + } + } + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +} + +export const lists_change_to_general = { + init: function () { + var OPERATORS = + [ + [Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, 'list'], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, 'tuple'], + [Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, 'set'] + ]; + this.setColour(LISTS_HUE); + this.appendValueInput('VAR'); + this.appendDummyInput("") + .appendField(Blockly.Msg.A_TO_B) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const lists_del_general = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('TUP') + this.appendDummyInput("") + .appendField(Blockly.Msg.OBJECT_DELETE); + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const list_tolist = { + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_TOLIST); + this.setOutput(true, 'List'); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOLIST); + } +}; + +export const lists_create_with2 = lists_create_with +export const lists_create_with_text2 = lists_create_with_text +export const lists_getIndex3 = lists_get_index +export const lists_getSublist3 = lists_get_sublist +export const lists_setIndex3 = lists_set_index +export const lists_insert_value2 = lists_insert_value +export const lists_remove_at2 = lists_remove_at +export const list_tolist2 = list_tolist; + + +export const ENUMERATE ={ + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.blockpy_USE_LIST); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TO_INDEX_SEQUENCE); + // this.appendValueInput('VAR_N') + // .appendField(Blockly.Msg.MIXLY_INDEX+Blockly.Msg.MIXLY_STARTSWITH); + this.setInputsInline(true); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOTO_INDEX_SEQUENC_TOOLTIP); + } +}; + +export const enumerate = { + init: function () { + this.setColour(LISTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_USE_LIST); + this.appendValueInput('LIST'); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.MIXLY_TO_INDEX_SEQUENCE) + .appendField(Blockly.Msg.MIXLY_INDEX+Blockly.Msg.MIXLY_STARTSWITH); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOTO_INDEX_SEQUENC_TOOLTIP); + } +}; + +export const content_in_lists = { + init: function () { + this.setColour(LISTS_HUE); + this.appendValueInput("CON") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_MIXGO_MUSIC_SHOW_IN); + this.appendValueInput("LIST") + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MID); + this.setInputsInline(true); + this.setOutput(true); + } +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/logic.js b/mixly/boards/default_src/python/blocks/logic.js new file mode 100644 index 00000000..2d693417 --- /dev/null +++ b/mixly/boards/default_src/python/blocks/logic.js @@ -0,0 +1,264 @@ +import * as Blockly from 'blockly/core'; + +const LOGIC_HUE = 210; + +export const logic_compare = { + /** + * Block for comparison operator. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = Blockly.RTL ? [ + ['=', 'EQ'], + ['\u2260', 'NEQ'], + ['>', 'LT'], + ['\u2265', 'LTE'], + ['<', 'GT'], + ['\u2264', 'GTE'] + ] : [ + ['=', 'EQ'], + ['\u2260', 'NEQ'], + ['<', 'LT'], + ['\u2264', 'LTE'], + ['>', 'GT'], + ['\u2265', 'GTE'] + ]; + //this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL); + this.setColour(LOGIC_HUE); + this.setOutput(true, Boolean); + this.appendValueInput('A'); + this.appendValueInput('B') + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'EQ': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ, + 'NEQ': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ, + 'LT': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT, + 'LTE': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE, + 'GT': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT, + 'GTE': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE + }; + return TOOLTIPS[op]; + }); + this.prevBlocks_ = [null, null]; + }, + /** + * Called whenever anything on the workspace changes. + * Prevent mismatched types from being compared. + * @this Blockly.Block + */ + /*onchange: function(e) { + var blockA = this.getInputTargetBlock('A'); + var blockB = this.getInputTargetBlock('B'); + // Disconnect blocks that existed prior to this change if they don't match. + if (blockA && blockB && + !blockA.outputConnection.checkType_(blockB.outputConnection)) { + // Mismatch between two inputs. Disconnect previous and bump it away. + // Ensure that any disconnections are grouped with the causing event. + Blockly.Events.setGroup(e.group); + for (var i = 0; i < this.prevBlocks_.length; i++) { + var block = this.prevBlocks_[i]; + if (block === blockA || block === blockB) { + block.unplug(); + block.bumpNeighbours_(); + } + } + Blockly.Events.setGroup(false); + } + this.prevBlocks_[0] = blockA; + this.prevBlocks_[1] = blockB; + }*/ +}; + +export const logic_compare_continous = { + + init: function () { + var OPERATORS1 = Blockly.RTL ? [ + ['>', 'LT'], + ['\u2265', 'LTE'], + ['<', 'GT'], + ['\u2264', 'GTE'] + ] : [ + ['<', 'LT'], + ['\u2264', 'LTE'], + ['>', 'GT'], + ['\u2265', 'GTE'] + ]; + var OPERATORS2 = Blockly.RTL ? [ + ['>', 'LT'], + ['\u2265', 'LTE'], + ['<', 'GT'], + ['\u2264', 'GTE'] + ] : [ + ['<', 'LT'], + ['\u2264', 'LTE'], + ['>', 'GT'], + ['\u2265', 'GTE'] + ]; + //this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL); + this.setColour(LOGIC_HUE); + this.setOutput(true, Boolean); + this.appendValueInput('A'); + this.appendValueInput('B') + .appendField(new Blockly.FieldDropdown(OPERATORS1), 'OP1'); + this.appendValueInput('C') + .appendField(new Blockly.FieldDropdown(OPERATORS2), 'OP2'); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_LOGIC_COMPARE_CONTINOUS_TOOLTIP); + + } +}; + +export const logic_operation = { + /** + * Block for logical operations: 'and', 'or'. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = [ + [Blockly.Msg.LOGIC_OPERATION_AND, 'AND'], + [Blockly.Msg.LOGIC_OPERATION_OR, 'OR'], + [Blockly.Msg.LOGIC_OPERATION_NOR, 'NOR'], + [Blockly.Msg.LOGIC_OPERATION_XOR, 'XOR'] + ]; + //this.setHelpUrl(Blockly.Msg.LOGIC_OPERATION_HELPURL); + this.setColour(LOGIC_HUE); + this.setOutput(true, Boolean); + this.appendValueInput('A') + .setCheck([Boolean, Number]); + this.appendValueInput('B') + .setCheck([Boolean, Number]) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var op = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'AND': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND, + 'OR': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR, + 'NOR': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_NOR, + 'XOR': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_XOR + }; + return TOOLTIPS[op]; + }); + } +}; + +export const logic_negate = { + /** + * Block for negation. + * @this Blockly.Block + */ + init: function () { + //this.setHelpUrl(Blockly.Msg.LOGIC_NEGATE_HELPURL); + this.setColour(LOGIC_HUE); + this.setOutput(true, Boolean); + this.appendValueInput('BOOL') + .setCheck([Number, Boolean]) + .appendField(Blockly.Msg.LOGIC_NEGATE_TITLE); + //this.interpolateMsg(Blockly.Msg.LOGIC_NEGATE_TITLE, + // ['BOOL', Boolean, Blockly.inputs.Align.RIGHT], + // Blockly.inputs.Align.RIGHT); + this.setTooltip(Blockly.Msg.LOGIC_NEGATE_TOOLTIP); + } +}; + +export const logic_boolean = { + /** + * Block for boolean data type: true and false. + * @this Blockly.Block + */ + init: function () { + var BOOLEANS = [ + [Blockly.Msg.LOGIC_BOOLEAN_TRUE, 'TRUE'], + [Blockly.Msg.LOGIC_BOOLEAN_FALSE, 'FALSE'] + ]; + //this.setHelpUrl(Blockly.Msg.LOGIC_BOOLEAN_HELPURL); + this.setColour(LOGIC_HUE); + this.setOutput(true, Boolean); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown(BOOLEANS), 'BOOL'); + this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP); + } +}; + +export const logic_null = { + /** + * Block for null data type. + * @this Blockly.Block + */ + init: function () { + //this.setHelpUrl(Blockly.Msg.LOGIC_NULL_HELPURL); + this.setColour(LOGIC_HUE); + this.setOutput(true); + this.appendDummyInput() + .appendField(Blockly.Msg.LOGIC_NULL); + this.setTooltip(Blockly.Msg.LOGIC_NULL_TOOLTIP); + } +}; + +export const logic_true_or_false = { + init: function () { + this.setColour(LOGIC_HUE); + this.appendValueInput('A'); + this.appendValueInput('B') + .appendField(Blockly.Msg.LOGIC_TERNARY_IF_TRUE); + this.appendValueInput('C') + .appendField(Blockly.Msg.LOGIC_TERNARY_IF_FALSE); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_LOGIT_TRUEORFALSE); + } +}; + +export const logic_is_in = { + init: function () { + var BOOLEANS = [ + [Blockly.Msg.TEXT_APPEND_TO, 'in'], + [Blockly.Msg.MIXLY_PYTHON_LOGIC_IS_NOT_IN, 'not in'] + ]; + this.setColour(LOGIC_HUE); + this.appendValueInput('A'); + this.appendValueInput('B') + .setCheck([String, 'List']) + //.appendField(Blockly.Msg.TEXT_APPEND_TO) + .appendField(new Blockly.FieldDropdown(BOOLEANS), 'BOOL'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MICROBIT_LOGIC_IS_IN); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.IN); + } +}; + +export const logic_is = { + init: function () { + var BOOLEANS = [ + [Blockly.Msg.MIXLY_PYTHON_LOGIC_IS, 'is'], + [Blockly.Msg.MIXLY_PYTHON_LOGIC_IS_NOT, 'is not'] + ]; + this.setColour(LOGIC_HUE); + this.appendValueInput('A'); + this.appendValueInput('B') + .appendField(new Blockly.FieldDropdown(BOOLEANS), 'BOOL'); + //.appendField(Blockly.Msg.MIXLY_PYTHON_LOGIC_IS); + this.setOutput(true, Boolean); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_LOGIC_IS_TOOLTIP); + } +}; + +export const logic_tobool = { + init: function () { + this.setColour(LOGIC_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_TOBOOL); + this.setOutput(true, Boolean); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOBOOL); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/math.js b/mixly/boards/default_src/python/blocks/math.js new file mode 100644 index 00000000..63419cb4 --- /dev/null +++ b/mixly/boards/default_src/python/blocks/math.js @@ -0,0 +1,701 @@ +import * as Blockly from 'blockly/core'; + +const MATH_HUE = 230; //'#e49f16'; + +Blockly.FieldTextInput.math_number_validator = function (text) { + //return window.isNaN(text) ? null : String(text); + // var pattern = /^-?(0X|0x|0O|0o|0B|0b)?[a-fA-F0-9]{1,}(\.[a-fA-F0-9]+)?$/; + // return pattern.test(text) ? String(text) : null;//校验,二 八 十 十六进制匹配 + return String(text);//不再校验 +}; + +Blockly.FieldTextInput.math_number_validator_include_blank = function (text) { + if (text === "") { + return ""; + } + var pattern = /^-?(0X|0x|0O|0o|0B|0b)?[a-fA-F0-9]{1,}(\.[a-fA-F0-9]+)?$/; + return pattern.test(text) ? String(text) : null;//校验,二 八 十 十六进制匹配 +}; + +export const math_number = { + /** + * Block for numeric value. + * @this Blockly.Block + */ + init: function () { + this.setColour(MATH_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput('0', + Blockly.FieldTextInput.math_number_validator), 'NUM'); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MATH_NUMBER_TOOLTIP); + } +}; + +export const math_constant = { + init: function () { + this.setColour(MATH_HUE); + var constant = + [['π', 'pi'], ['e', 'e']]; + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_PYTHON_MATH_CONSTANT) + .appendField(new Blockly.FieldDropdown(constant), 'CONSTANT') + + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('CONSTANT'); + var TOOLTIPS = { + 'pi': Blockly.Msg.MIXLY_PYTHON_MATH_CONSTANT_PI_TOOLTIP, + 'e': Blockly.Msg.MIXLY_PYTHON_MATH_CONSTANT_E_TOOLTIP + }; + return TOOLTIPS[mode]; + }); + + } +}; + +export const math_constant_mp = { + init: function () { + this.setColour(MATH_HUE); + var constant = + [['π', 'pi'], ['e', 'e']]; + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_PYTHON_MATH_CONSTANT) + .appendField(new Blockly.FieldDropdown(constant), 'CONSTANT') + + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('CONSTANT'); + var TOOLTIPS = { + 'pi': Blockly.Msg.MIXLY_PYTHON_MATH_CONSTANT_PI_MP_TOOLTIP, + 'e': Blockly.Msg.MIXLY_PYTHON_MATH_CONSTANT_E_MP_TOOLTIP + }; + return TOOLTIPS[mode]; + }); + + } +}; + +export const math_arithmetic = { + /** + * Block for basic arithmetic operator. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = [ + ['+', 'ADD'], + ['-', 'MINUS'], + ['×', 'MULTIPLY'], + ['÷', 'DIVIDE'], + ['%', 'QUYU'], + ['//', 'ZHENGCHU'], + ['**', 'POWER'] + ]; + //this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL); + this.setColour(MATH_HUE); + this.setOutput(true); + this.appendValueInput('A') + this.appendValueInput('B') + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD, + 'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS, + 'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY, + 'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE, + 'QUYU': Blockly.Msg.MATH_MODULO_TOOLTIP, + 'ZHENGCHU': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE, + 'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const math_selfcalcu = { + /** + * Block for basic arithmetic operator. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = [ + ['+=', 'ADD'], + ['-=', 'MINUS'], + ['×=', 'MULTIPLY'], + ['÷=', 'DIVIDE'], + ['%=', 'QUYU'], + ['//=', 'ZHENGCHU'], + ['**=', 'POWER'] + ]; + + this.setColour(MATH_HUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendValueInput('A') + this.appendValueInput('B') + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD, + 'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS, + 'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY, + 'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE, + 'QUYU': Blockly.Msg.MATH_MODULO_TOOLTIP, + 'ZHENGCHU': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE, + 'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const math_bit = { + init: function () { + var OPERATORS = [ + ['&', '&'], + ['|', '|'], + ['>>', '>>'], + ['<<', '<<'] + ]; + this.setColour(MATH_HUE); + this.setOutput(true, Number); + this.appendValueInput('A') + .setCheck(Number); + this.appendValueInput('B') + .setCheck(Number) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + this.setTooltip("位运算"); + } +}; + +export const math_trig = { + /** + * Block for trigonometry operators. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = [ + ['sin', 'SIN'], + ['cos', 'COS'], + ['tan', 'TAN'], + ['asin', 'ASIN'], + ['acos', 'ACOS'], + ['atan', 'ATAN'], + ['-', '-'], + ['ln', 'LN'], + ['log10', 'LOG10'], + ['e^', 'EXP'], + ['10^', 'POW10'] + ]; + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(MATH_HUE); + this.setOutput(true, Number); + this.appendValueInput('NUM') + .setCheck(Number) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'SIN': Blockly.Msg.MATH_TRIG_TOOLTIP_SIN, + 'COS': Blockly.Msg.MATH_TRIG_TOOLTIP_COS, + 'TAN': Blockly.Msg.MATH_TRIG_TOOLTIP_TAN, + 'ASIN': Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN, + 'ACOS': Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS, + 'ATAN': Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN, + 'LN': Blockly.Msg.MATH_SINGLE_TOOLTIP_LN + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const math_dec = { + /** + * Block for trigonometry operators. + * @this Blockly.Block + */ + init: function () { + var OPERATORS = [ + [Blockly.Msg.MATH_BIN, 'bin'], + [Blockly.Msg.MATH_OCT, 'oct'], + [Blockly.Msg.MATH_HEX, 'hex'], + ]; + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(MATH_HUE); + this.setOutput(true, String); + this.appendValueInput('NUM') + .setCheck(Number) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'bin': Blockly.Msg.MATH_DEC_TOOLTIP_BIN, + 'oct': Blockly.Msg.MATH_DEC_TOOLTIP_OCT, + 'hex': Blockly.Msg.MATH_DEC_TOOLTIP_HEX, + + }; + return TOOLTIPS[mode]; + }); + } +}; + +//取整等 +export const math_to_int = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.LANG_MATH_TO_ROUND, 'round'], + [Blockly.Msg.LANG_MATH_TO_CEIL, 'ceil'], + [Blockly.Msg.LANG_MATH_TO_FLOOR, 'floor'], + [Blockly.Msg.MATH_ABS, 'fabs'], + // [Blockly.Msg.MATH_SQ, 'pow'], + [Blockly.Msg.MATH_SQRT, 'sqrt'] + ]; + this.setColour(MATH_HUE); + this.appendValueInput('A') + .setCheck(Number) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'sqrt': Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT, + 'fabs': Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS, + 'sq': Blockly.Msg.MATH_SINGLE_TOOLTIP_SQ, + 'round': Blockly.Msg.MATH_SINGLE_TOOLTIP_ROUND, + 'ceil': Blockly.Msg.MATH_SINGLE_TOOLTIP_CEIL, + 'floor': Blockly.Msg.MATH_SINGLE_TOOLTIP_FLOOR + }; + return TOOLTIPS[mode]; + }); + } +}; +//最大最小值 +export const math_max_min = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MIXLY_MAX, 'max'], + [Blockly.Msg.MIXLY_MIN, 'min'], + ]; + + this.setColour(MATH_HUE); + this.appendValueInput('A') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP') + .appendField('('); + this.appendValueInput('B') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(','); + this.appendDummyInput('') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(')'); + this.setInputsInline(true); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'max': Blockly.Msg.MIXLY_TOOLTIP_MATH_MAX, + 'min': Blockly.Msg.MIXLY_TOOLTIP_MATH_MIN + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const math_number_base_conversion = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MATH_TWO, 'two'], + [Blockly.Msg.MATH_EIGHT, 'eight'], + [Blockly.Msg.MATH_TEN, 'ten'], + [Blockly.Msg.MATH_SIXTEEN, 'sixteen'] + ]; + this.setColour(MATH_HUE); + this.appendDummyInput('') + .appendField(Blockly.Msg.MATH_BA) + this.appendValueInput("NUM") + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP') + .appendField(Blockly.Msg.MATH_JinZhi) + .setCheck(Number); + this.appendDummyInput("") + .appendField(Blockly.Msg.MATH_ZHW) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP2') + .appendField(Blockly.Msg.MATH_JinZhi); + this.setFieldValue('ten', 'OP2') + // this.setPreviousStatement(true, null); + // this.setNextStatement(true, null); + this.setOutput(true) + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'two': Blockly.Msg.MATH_Before_two, + 'eight': Blockly.Msg.MATH_Before_eight, + 'ten': Blockly.Msg.MATH_Before_ten, + 'sixteen': Blockly.Msg.MATH_Before_sixteen, + }; + var mode2 = thisBlock.getFieldValue('OP2'); + var TOOLTIPS2 = { + 'two': Blockly.Msg.MATH_Behind_two, + 'eight': Blockly.Msg.MATH_Behind_eight, + 'ten': Blockly.Msg.MATH_Behind_ten, + 'sixteen': Blockly.Msg.MATH_Behind_sixteen, + }; + return TOOLTIPS[mode] + TOOLTIPS2[mode2]; + }); + } +}; + + +export const math_random = { + init: function () { + var INT_FLOAT = [[Blockly.Msg.LANG_MATH_INT, 'int'], [Blockly.Msg.LANG_MATH_FLOAT, 'float']]; + this.setColour(MATH_HUE); + this.setOutput(true, Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_RANDOM) + .appendField(new Blockly.FieldDropdown(INT_FLOAT), 'TYPE'); + this.appendValueInput('FROM') + .setCheck(Number) + .appendField(Blockly.Msg.LANG_CONTROLS_FOR_INPUT_FROM); + this.appendValueInput('TO') + .setCheck(Number) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg.LANG_MATH_RANDOM_INT_INPUT_TO); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('TYPE'); + var TOOLTIPS = { + 'int': Blockly.Msg.LANG_MATH_INT, + 'float': Blockly.Msg.LANG_MATH_FLOAT_RANDOM + }; + return Blockly.Msg.MATH_RANDOM_INT_TOOLTIP + TOOLTIPS[mode]; + }); + } +}; + + +export const math_constrain = { + /** + * Block for constraining a number between two limits. + * @this Blockly.Block + */ + init: function () { + this.setColour(MATH_HUE); + this.setOutput(true, Number); + this.appendValueInput('VALUE') + .setCheck(Number) + .appendField(Blockly.Msg.LANG_MATH_CONSTRAIN_INPUT_CONSTRAIN); + this.appendValueInput('LOW') + .setCheck(Number) + .appendField(Blockly.Msg.LANG_MATH_CONSTRAIN_INPUT_LOW); + this.appendValueInput('HIGH') + .setCheck(Number) + .appendField(Blockly.Msg.LANG_MATH_CONSTRAIN_INPUT_HIGH); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MATH_CONSTRAIN_TOOLTIP); + } +}; + +export const math_map = { + init: function () { + this.setColour(MATH_HUE); + this.appendValueInput("NUM", Number) + .appendField(Blockly.Msg.MIXLY_MAP) + .setCheck(Number); + this.appendValueInput("fromLow", Number) + .appendField(Blockly.Msg.MIXLY_MAP_FROM) + .setCheck(Number); + this.appendValueInput("fromHigh", Number) + .appendField(",") + .setCheck(Number); + this.appendValueInput("toLow", Number) + .appendField(Blockly.Msg.MIXLY_MAP_TO) + .setCheck(Number); + this.appendValueInput("toHigh", Number) + .appendField(",") + .setCheck(Number); + this.appendDummyInput("") + .appendField("]"); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_MATH_MAP); + } +}; + +export const math_indexer_number = { + /** + * Block for numeric value. + * @this Blockly.Block + */ + init: function () { + this.setColour(MATH_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput('0', Blockly.FieldTextInput.math_number_validator_include_blank), 'NUM'); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MATH_NUMBER_TOOLTIP); + } +}; + +export const math_random_seed = { + init: function () { + this.setColour(MATH_HUE); + this.appendValueInput('NUM') + .setCheck(Number) + .appendField(Blockly.Msg.LANG_MATH_RANDOM_SEED); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_MATH_RANDOM_SEED); + } +}; + +export const math_round = { + + init: function () { + this.setColour(MATH_HUE); + this.setOutput(true, Number); + this.appendValueInput('VALUE') + .setCheck(Number) + this.appendValueInput('VAR') + .setCheck(Number) + .appendField(Blockly.Msg.MATH_ROUND) + .appendField(Blockly.Msg.TEXT_KEEP); + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_DECIMAL); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MATH_ROUND_NEW_TOOLTIP); + } +}; + +export const text_to_number = { + init: function () { + var TO_INT_FLOAT = + [[Blockly.Msg.MIXLY_TO_INT, 'int'], [Blockly.Msg.MIXLY_TO_FLOAT, 'float'], [Blockly.Msg.MIXLY_TO_BITES, 'b'], [Blockly.Msg.LANG_MATH_BYTE + Blockly.Msg.MIXLY_TO_INT, 'bti']]; + this.setColour(MATH_HUE); + this.appendValueInput('VAR') + .appendField(new Blockly.FieldDropdown(TO_INT_FLOAT), 'TOWHAT'); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('TOWHAT'); + var TOOLTIPS = { + 'int': Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOINT, + 'float': Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOFLOAT, + 'b': Blockly.Msg.MIXLY_TOOLTIP_TEXT_TOBYTE + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const text_to_number_skulpt = { + init: function () { + var TO_INT_FLOAT = + [[Blockly.Msg.MIXLY_TO_INT, 'int'], [Blockly.Msg.MIXLY_TO_FLOAT, 'float']]; + this.setColour(MATH_HUE); + this.appendValueInput('VAR') + .appendField(new Blockly.FieldDropdown(TO_INT_FLOAT), 'TOWHAT'); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('TOWHAT'); + var TOOLTIPS = { + 'int': Blockly.Msg.MIXLY_TOOLTIP_TEXT_TOINT, + 'float': Blockly.Msg.MIXLY_TOOLTIP_TEXT_TOFLOAT + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const base_map = math_map + +export const turn_to_int = { + init: function () { + this.setColour(MATH_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.LANG_MATH_BYTE + Blockly.Msg.MIXLY_TO_HEX); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOHEX) + } +}; + +export const generate_cartesian_product = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(MATH_HUE); + this.itemCount_ = 1; + this.setMutator(new Blockly.icons.MutatorIcon(['lists_create_with_item'], this)); + this.appendDummyInput('DUMMY') + .appendField(Blockly.Msg.MIXLY_PRODUCT + Blockly.Msg.MIXLY_GENERATE_CARTESIAN_PRODUCT); + this.appendValueInput('REPEAT') + .appendField(Blockly.Msg.MIXLY_EVERY_PER_ELEPER_ELEMENT); + this.appendDummyInput() + .appendField(Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true); + this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_PYTHON_TOOLTIP); + this.updateShape_(); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('lists_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('lists_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput(`ADD${i}`).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput(`ADD${i}`); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + let i = 0; + while (this.getInput(`ADD${i}`)) { + this.removeInput(`ADD${i}`); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.MIXLY_EMPTY_REMINDER); + } else { + for (let i = 0; i < this.itemCount_; i++) { + this.appendValueInput(`ADD${i}`); + this.moveInputBefore(`ADD${i}`, 'REPEAT'); + } + } + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +} + +export const math_radian_to_degree = { + init: function () { + this.setColour(MATH_HUE); + this.setOutput(true) + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_SET_RADIAN); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TRANS_TO_ANGLE); + this.setInputsInline(true); + } +}; + +export const math_degree_to_radian = { + init: function () { + this.setColour(MATH_HUE); + this.setOutput(true) + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_SET_DEGREE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TRANS_TO_RADIAN); + this.setInputsInline(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/procedures.js b/mixly/boards/default_src/python/blocks/procedures.js new file mode 100644 index 00000000..b9ef06ca --- /dev/null +++ b/mixly/boards/default_src/python/blocks/procedures.js @@ -0,0 +1,1249 @@ +/** + * @license + * Copyright 2012 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Procedure blocks for Blockly. + * @author fraser@google.com (Neil Fraser) + */ +import * as Blockly from 'blockly/core'; +import { Variables, Procedures } from 'blockly/core'; + +export const procedures_defnoreturn = { + /** + * Block for defining a procedure with no return value. + * @this {Blockly.Block} + */ + init: function () { + var initName = Procedures.findLegalName('', this); + var nameField = new Blockly.FieldTextInput(initName, + Procedures.rename); + nameField.setSpellcheck(false); + this.appendDummyInput() + // .appendField(Blockly.Msg['PROCEDURES_DEFNORETURN_TITLE']) + .appendField(nameField, 'NAME') + .appendField('', 'PARAMS'); + this.setMutator(new Blockly.icons.MutatorIcon(['procedures_mutatorarg'], this)); + if ((this.workspace.options.comments || + (this.workspace.options.parentWorkspace && + this.workspace.options.parentWorkspace.options.comments)) && + Blockly.Msg['PROCEDURES_DEFNORETURN_COMMENT']) { + this.setCommentText(Blockly.Msg['PROCEDURES_DEFNORETURN_COMMENT']); + } + this.setStyle('procedure_blocks'); + this.setTooltip(Blockly.Msg['PROCEDURES_DEFNORETURN_TOOLTIP']); + this.setHelpUrl(Blockly.Msg['PROCEDURES_DEFNORETURN_HELPURL']); + this.arguments_ = []; + this.argumentVarModels_ = []; + this.setStatements_(true); + this.statementConnection_ = null; + }, + /** + * Add or remove the statement block from this function definition. + * @param {boolean} hasStatements True if a statement block is needed. + * @this {Blockly.Block} + */ + setStatements_: function (hasStatements) { + if (this.hasStatements_ === hasStatements) { + return; + } + if (hasStatements) { + this.appendStatementInput('STACK') + .appendField(Blockly.Msg['PROCEDURES_DEFNORETURN_DO']); + if (this.getInput('RETURN')) { + this.moveInputBefore('STACK', 'RETURN'); + } + } else { + this.removeInput('STACK', true); + } + this.hasStatements_ = hasStatements; + }, + /** + * Update the display of parameters for this procedure definition block. + * @private + * @this {Blockly.Block} + */ + updateParams_: function () { + // Merge the arguments into a human-readable list. + var paramString = ''; + if (this.arguments_.length) { + paramString = Blockly.Msg['PROCEDURES_BEFORE_PARAMS'] + + ' ' + this.arguments_.join(', '); + } + // The params field is deterministic based on the mutation, + // no need to fire a change event. + Blockly.Events.disable(); + try { + this.setFieldValue(paramString, 'PARAMS'); + } finally { + Blockly.Events.enable(); + } + }, + /** + * Create XML to represent the argument inputs. + * @param {boolean=} opt_paramIds If true include the IDs of the parameter + * quarks. Used by Procedures.mutateCallers for reconnection. + * @return {!Element} XML storage element. + * @this {Blockly.Block} + */ + mutationToDom: function (opt_paramIds) { + var container = Blockly.utils.xml.createElement('mutation'); + if (opt_paramIds) { + container.setAttribute('name', this.getFieldValue('NAME')); + } + for (var i = 0; i < this.argumentVarModels_.length; i++) { + var parameter = Blockly.utils.xml.createElement('arg'); + var argModel = this.argumentVarModels_[i]; + parameter.setAttribute('name', argModel.name); + parameter.setAttribute('varid', argModel.getId()); + if (opt_paramIds && this.paramIds_) { + parameter.setAttribute('paramId', this.paramIds_[i]); + } + container.appendChild(parameter); + } + + // Save whether the statement input is visible. + if (!this.hasStatements_) { + container.setAttribute('statements', 'false'); + } + return container; + }, + /** + * Parse XML to restore the argument inputs. + * @param {!Element} xmlElement XML storage element. + * @this {Blockly.Block} + */ + domToMutation: function (xmlElement) { + this.arguments_ = []; + this.argumentVarModels_ = []; + for (var i = 0, childNode; (childNode = xmlElement.childNodes[i]); i++) { + if (childNode.nodeName.toLowerCase() == 'arg') { + var varName = childNode.getAttribute('name'); + var varId = childNode.getAttribute('varid') || childNode.getAttribute('varId'); + this.arguments_.push(varName); + var variable = Blockly.Variables.getOrCreateVariablePackage( + this.workspace, varId, varName, ''); + if (variable != null) { + this.argumentVarModels_.push(variable); + } else { + console.log('Failed to create a variable with name ' + varName + ', ignoring.'); + } + } + } + this.updateParams_(); + Procedures.mutateCallers(this); + + // Show or hide the statement input. + this.setStatements_(xmlElement.getAttribute('statements') !== 'false'); + }, + /** + * Returns the state of this block as a JSON serializable object. + * + * @returns The state of this block, eg the parameters and statements. + */ + saveExtraState: function () { + if (!this.argumentVarModels_.length && this.hasStatements_) { + return null; + } + const state = Object.create(null); + if (this.argumentVarModels_.length) { + state['params'] = []; + for (let i = 0; i < this.argumentVarModels_.length; i++) { + state['params'].push({ + // We don't need to serialize the name, but just in case we decide + // to separate params from variables. + 'name': this.argumentVarModels_[i].name, + 'id': this.argumentVarModels_[i].getId(), + }); + } + } + if (!this.hasStatements_) { + state['hasStatements'] = false; + } + return state; + }, + /** + * Applies the given state to this block. + * + * @param state The state to apply to this block, eg the parameters + * and statements. + */ + loadExtraState: function (state) { + this.arguments_ = []; + this.argumentVarModels_ = []; + if (state['params']) { + for (let i = 0; i < state['params'].length; i++) { + const param = state['params'][i]; + const variable = Variables.getOrCreateVariablePackage( + this.workspace, + param['id'], + param['name'], + '', + ); + this.arguments_.push(variable.name); + this.argumentVarModels_.push(variable); + } + } + this.updateParams_(); + Procedures.mutateCallers(this); + this.setStatements_(state['hasStatements'] !== false); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this {Blockly.Block} + */ + decompose: function (workspace) { + /* + * Creates the following XML: + * + * + * + * arg1_name + * etc... + * + * + * + */ + + var containerBlockNode = Blockly.utils.xml.createElement('block'); + containerBlockNode.setAttribute('type', 'procedures_mutatorcontainer'); + var statementNode = Blockly.utils.xml.createElement('statement'); + statementNode.setAttribute('name', 'STACK'); + containerBlockNode.appendChild(statementNode); + + var node = statementNode; + for (var i = 0; i < this.arguments_.length; i++) { + var argBlockNode = Blockly.utils.xml.createElement('block'); + argBlockNode.setAttribute('type', 'procedures_mutatorarg'); + var fieldNode = Blockly.utils.xml.createElement('field'); + fieldNode.setAttribute('name', 'NAME'); + var argumentName = Blockly.utils.xml.createTextNode(this.arguments_[i]); + fieldNode.appendChild(argumentName); + argBlockNode.appendChild(fieldNode); + var nextNode = Blockly.utils.xml.createElement('next'); + argBlockNode.appendChild(nextNode); + + node.appendChild(argBlockNode); + node = nextNode; + } + + var containerBlock = Blockly.Xml.domToBlock(containerBlockNode, workspace); + + if (this.type == 'procedures_defreturn') { + containerBlock.setFieldValue(this.hasStatements_, 'STATEMENTS'); + } else { + containerBlock.removeInput('STATEMENT_INPUT'); + } + + // Initialize procedure's callers with blank IDs. + Procedures.mutateCallers(this); + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this {Blockly.Block} + */ + compose: function (containerBlock) { + // Parameter list. + this.arguments_ = []; + this.paramIds_ = []; + this.argumentVarModels_ = []; + var paramBlock = containerBlock.getInputTargetBlock('STACK'); + while (paramBlock && !paramBlock.isInsertionMarker()) { + var varName = paramBlock.getFieldValue('NAME'); + this.arguments_.push(varName); + var variable = this.workspace.getVariable(varName, ''); + this.argumentVarModels_.push(variable); + + this.paramIds_.push(paramBlock.id); + paramBlock = paramBlock.nextConnection && + paramBlock.nextConnection.targetBlock(); + } + this.updateParams_(); + Procedures.mutateCallers(this); + + // Show/hide the statement input. + var hasStatements = containerBlock.getFieldValue('STATEMENTS'); + if (hasStatements !== null) { + hasStatements = hasStatements == 'TRUE'; + if (this.hasStatements_ != hasStatements) { + if (hasStatements) { + this.setStatements_(true); + // Restore the stack, if one was saved. + this.statementConnection_ && this.statementConnection_.reconnect(this, 'STACK'); + this.statementConnection_ = null; + } else { + // Save the stack, then disconnect it. + var stackConnection = this.getInput('STACK').connection; + this.statementConnection_ = stackConnection.targetConnection; + if (this.statementConnection_) { + var stackBlock = stackConnection.targetBlock(); + stackBlock.unplug(); + stackBlock.bumpNeighbours(); + } + this.setStatements_(false); + } + } + } + }, + /** + * Return the signature of this procedure definition. + * @return {!Array} Tuple containing three elements: + * - the name of the defined procedure, + * - a list of all its arguments, + * - that it DOES NOT have a return value. + * @this {Blockly.Block} + */ + getProcedureDef: function () { + return [this.getFieldValue('NAME'), this.arguments_, false]; + }, + /** + * Return all variables referenced by this block. + * @return {!Array} List of variable names. + * @this {Blockly.Block} + */ + getVars: function () { + return this.arguments_; + }, + /** + * Return all variables referenced by this block. + * @return {!Array} List of variable models. + * @this {Blockly.Block} + */ + getVarModels: function () { + return this.argumentVarModels_; + }, + /** + * Notification that a variable is renaming. + * If the ID matches one of this block's variables, rename it. + * @param {string} oldId ID of variable to rename. + * @param {string} newId ID of new variable. May be the same as oldId, but + * with an updated name. Guaranteed to be the same type as the old + * variable. + * @override + * @this {Blockly.Block} + */ + renameVarById: function (oldId, newId) { + var oldVariable = this.workspace.getVariableById(oldId); + if (oldVariable.type != '') { + // Procedure arguments always have the empty type. + return; + } + var oldName = oldVariable.name; + var newVar = this.workspace.getVariableById(newId); + + var change = false; + for (var i = 0; i < this.argumentVarModels_.length; i++) { + if (this.argumentVarModels_[i].getId() == oldId) { + this.arguments_[i] = newVar.name; + this.argumentVarModels_[i] = newVar; + change = true; + } + } + if (change) { + this.displayRenamedVar_(oldName, newVar.name); + Procedures.mutateCallers(this); + } + }, + /** + * Notification that a variable is renaming but keeping the same ID. If the + * variable is in use on this block, rerender to show the new name. + * @param {!Blockly.VariableModel} variable The variable being renamed. + * @package + * @override + * @this {Blockly.Block} + */ + updateVarName: function (variable) { + var newName = variable.name; + var change = false; + for (var i = 0; i < this.argumentVarModels_.length; i++) { + if (this.argumentVarModels_[i].getId() == variable.getId()) { + var oldName = this.arguments_[i]; + this.arguments_[i] = newName; + change = true; + } + } + if (change) { + this.displayRenamedVar_(oldName, newName); + Procedures.mutateCallers(this); + } + }, + /** + * Update the display to reflect a newly renamed argument. + * @param {string} oldName The old display name of the argument. + * @param {string} newName The new display name of the argument. + * @private + * @this {Blockly.Block} + */ + displayRenamedVar_: function (oldName, newName) { + this.updateParams_(); + const mutator = this.getIcon(Blockly.icons.MutatorIcon.TYPE); + // Update the mutator's variables if the mutator is open. + if (mutator && mutator.bubbleIsVisible()) { + var blocks = mutator.getWorkspace().getAllBlocks(false); + for (var i = 0, block; (block = blocks[i]); i++) { + if (block.type == 'procedures_mutatorarg' && + Blockly.Names.equals(oldName, block.getFieldValue('NAME'))) { + block.setFieldValue(newName, 'NAME'); + } + } + } + }, + /** + * Add custom menu options to this block's context menu. + * @param {!Array} options List of menu options to add to. + * @this {Blockly.Block} + */ + customContextMenu: function (options) { + if (this.isInFlyout) { + return; + } + // Add option to create caller. + var option = { enabled: true }; + var name = this.getFieldValue('NAME'); + option.text = Blockly.Msg['PROCEDURES_CREATE_DO'].replace('%1', name); + var xmlMutation = Blockly.utils.xml.createElement('mutation'); + xmlMutation.setAttribute('name', name); + for (var i = 0; i < this.arguments_.length; i++) { + var xmlArg = Blockly.utils.xml.createElement('arg'); + xmlArg.setAttribute('name', this.arguments_[i]); + xmlMutation.appendChild(xmlArg); + } + var xmlBlock = Blockly.utils.xml.createElement('block'); + xmlBlock.setAttribute('type', this.callType_); + xmlBlock.appendChild(xmlMutation); + option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock); + options.push(option); + + // Add options to create getters for each parameter. + if (!this.isCollapsed()) { + for (var i = 0; i < this.argumentVarModels_.length; i++) { + var argOption = { enabled: true }; + var argVar = this.argumentVarModels_[i]; + argOption.text = Blockly.Msg['VARIABLES_SET_CREATE_GET'] + .replace('%1', argVar.name); + + var argXmlField = Blockly.Variables.generateVariableFieldDom(argVar); + var argXmlBlock = Blockly.utils.xml.createElement('block'); + argXmlBlock.setAttribute('type', 'variables_get'); + argXmlBlock.appendChild(argXmlField); + argOption.callback = + Blockly.ContextMenu.callbackFactory(this, argXmlBlock); + options.push(argOption); + } + } + }, + callType_: 'procedures_callnoreturn' +}; + +export const procedures_defreturn = { + /** + * Block for defining a procedure with a return value. + * @this {Blockly.Block} + */ + init: function () { + var initName = Procedures.findLegalName('', this); + var nameField = new Blockly.FieldTextInput(initName, + Procedures.rename); + nameField.setSpellcheck(false); + this.appendDummyInput() + // .appendField(Blockly.Msg['PROCEDURES_DEFRETURN_TITLE']) + .appendField(nameField, 'NAME') + .appendField('', 'PARAMS'); + this.appendValueInput('RETURN') + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']); + this.setMutator(new Blockly.icons.MutatorIcon(['procedures_mutatorarg'], this)); + if ((this.workspace.options.comments || + (this.workspace.options.parentWorkspace && + this.workspace.options.parentWorkspace.options.comments)) && + Blockly.Msg['PROCEDURES_DEFRETURN_COMMENT']) { + this.setCommentText(Blockly.Msg['PROCEDURES_DEFRETURN_COMMENT']); + } + this.setStyle('procedure_blocks'); + this.setTooltip(Blockly.Msg['PROCEDURES_DEFRETURN_TOOLTIP']); + this.setHelpUrl(Blockly.Msg['PROCEDURES_DEFRETURN_HELPURL']); + this.arguments_ = []; + this.argumentVarModels_ = []; + this.setStatements_(true); + this.statementConnection_ = null; + }, + setStatements_: procedures_defnoreturn.setStatements_, + updateParams_: procedures_defnoreturn.updateParams_, + mutationToDom: procedures_defnoreturn.mutationToDom, + domToMutation: procedures_defnoreturn.domToMutation, + decompose: procedures_defnoreturn.decompose, + compose: procedures_defnoreturn.compose, + /** + * Return the signature of this procedure definition. + * @return {!Array} Tuple containing three elements: + * - the name of the defined procedure, + * - a list of all its arguments, + * - that it DOES have a return value. + * @this {Blockly.Block} + */ + getProcedureDef: function () { + return [this.getFieldValue('NAME'), this.arguments_, true]; + }, + getVars: procedures_defnoreturn.getVars, + getVarModels: procedures_defnoreturn.getVarModels, + renameVarById: procedures_defnoreturn.renameVarById, + updateVarName: procedures_defnoreturn.updateVarName, + displayRenamedVar_: procedures_defnoreturn.displayRenamedVar_, + customContextMenu: procedures_defnoreturn.customContextMenu, + callType_: 'procedures_callreturn' +}; + +export const procedures_mutatorcontainer = { + /** + * Mutator block for procedure container. + * @this {Blockly.Block} + */ + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg['PROCEDURES_MUTATORCONTAINER_TITLE']); + this.appendStatementInput('STACK'); + this.appendDummyInput('STATEMENT_INPUT') + .appendField(Blockly.Msg['PROCEDURES_ALLOW_STATEMENTS']) + .appendField(new Blockly.FieldCheckbox('TRUE'), 'STATEMENTS'); + this.setStyle('procedure_blocks'); + this.setTooltip(Blockly.Msg['PROCEDURES_MUTATORCONTAINER_TOOLTIP']); + this.contextMenu = false; + }, +}; + +export const procedures_mutatorarg = { + /** + * Mutator block for procedure argument. + * @this {Blockly.Block} + */ + init: function () { + var field = new Blockly.FieldTextInput( + Procedures.DEFAULT_ARG, this.validator_); + // Hack: override showEditor to do just a little bit more work. + // We don't have a good place to hook into the start of a text edit. + field.oldShowEditorFn_ = field.showEditor_; + var newShowEditorFn = function () { + this.createdVariables_ = []; + this.oldShowEditorFn_(); + }; + field.showEditor_ = newShowEditorFn; + + this.appendDummyInput() + .appendField(Blockly.Msg.PROCEDURES_BEFORE_PARAMS) + .appendField(field, 'NAME'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setStyle('procedure_blocks'); + this.setTooltip(Blockly.Msg['PROCEDURES_MUTATORARG_TOOLTIP']); + this.contextMenu = false; + + // Create the default variable when we drag the block in from the flyout. + // Have to do this after installing the field on the block. + field.onFinishEditing_ = this.deleteIntermediateVars_; + // Create an empty list so onFinishEditing_ has something to look at, even + // though the editor was never opened. + field.createdVariables_ = []; + field.onFinishEditing_('x'); + }, + /** + * Obtain a valid name for the procedure argument. Create a variable if + * necessary. + * Merge runs of whitespace. Strip leading and trailing whitespace. + * Beyond this, all names are legal. + * @param {string} varName User-supplied name. + * @return {?string} Valid name, or null if a name was not specified. + * @private + * @this Blockly.FieldTextInput + */ + validator_: function (varName) { + var sourceBlock = this.getSourceBlock(); + + var outerWs = sourceBlock.workspace.getRootWorkspace(); + varName = varName.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, ''); + if (!varName) { + return null; + } + + // Prevents duplicate parameter names in functions + var workspace = sourceBlock.workspace.targetWorkspace || + sourceBlock.workspace; + var blocks = workspace.getAllBlocks(false); + var caselessName = varName.toLowerCase(); + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].id == this.getSourceBlock().id) { + continue; + } + // Other blocks values may not be set yet when this is loaded. + var otherVar = blocks[i].getFieldValue('NAME'); + if (otherVar && otherVar.toLowerCase() == caselessName) { + return null; + } + } + + // Don't create variables for arg blocks that + // only exist in the mutator's flyout. + if (sourceBlock.isInFlyout) { + return varName; + } + + var model = outerWs.getVariable(varName, ''); + if (model && model.name != varName) { + // Rename the variable (case change) + outerWs.renameVariableById(model.getId(), varName); + } + if (!model) { + model = outerWs.createVariable(varName, ''); + if (model && this.createdVariables_) { + this.createdVariables_.push(model); + } + } + return varName; + }, + + /** + * Called when focusing away from the text field. + * Deletes all variables that were created as the user typed their intended + * variable name. + * @param {string} newText The new variable name. + * @private + * @this Blockly.FieldTextInput + */ + deleteIntermediateVars_: function (newText) { + var outerWs = this.getSourceBlock().workspace.getRootWorkspace(); + if (!outerWs) { + return; + } + for (var i = 0; i < this.createdVariables_.length; i++) { + var model = this.createdVariables_[i]; + if (model.name != newText) { + outerWs.deleteVariableById(model.getId()); + } + } + } +}; + +export const procedures_callnoreturn = { + /** + * Block for calling a procedure with no return value. + * @this {Blockly.Block} + */ + init: function () { + this.appendDummyInput('TOPROW') + .appendField('', 'NAME'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setStyle('procedure_blocks'); + // Tooltip is set in renameProcedure. + this.setHelpUrl(Blockly.Msg['PROCEDURES_CALLNORETURN_HELPURL']); + this.arguments_ = []; + this.argumentVarModels_ = []; + this.quarkConnections_ = {}; + this.quarkIds_ = null; + this.previousEnabledState_ = true; + }, + /** + * Returns the name of the procedure this block calls. + * @return {string} Procedure name. + * @this {Blockly.Block} + */ + getProcedureCall: function () { + // The NAME field is guaranteed to exist, null will never be returned. + return /** @type {string} */ (this.getFieldValue('NAME')); + }, + /** + * Notification that a procedure is renaming. + * If the name matches this block's procedure, rename it. + * @param {string} oldName Previous name of procedure. + * @param {string} newName Renamed procedure. + * @this {Blockly.Block} + */ + renameProcedure: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getProcedureCall())) { + this.setFieldValue(newName, 'NAME'); + var baseMsg = this.outputConnection ? + Blockly.Msg['PROCEDURES_CALLRETURN_TOOLTIP'] : + Blockly.Msg['PROCEDURES_CALLNORETURN_TOOLTIP']; + this.setTooltip(baseMsg.replace('%1', newName)); + } + }, + /** + * Notification that the procedure's parameters have changed. + * @param {!Array} paramNames New param names, e.g. ['x', 'y', 'z']. + * @param {!Array} paramIds IDs of params (consistent for each + * parameter through the life of a mutator, regardless of param renaming), + * e.g. ['piua', 'f8b_', 'oi.o']. + * @private + * @this {Blockly.Block} + */ + setProcedureParameters_: function (paramNames, paramIds) { + // Data structures: + // this.arguments = ['x', 'y'] + // Existing param names. + // this.quarkConnections_ {piua: null, f8b_: Connection} + // Look-up of paramIds to connections plugged into the call block. + // this.quarkIds_ = ['piua', 'f8b_'] + // Existing param IDs. + // Note that quarkConnections_ may include IDs that no longer exist, but + // which might reappear if a param is reattached in the mutator. + const defBlock = Procedures.getDefinition( + this.getProcedureCall(), + this.workspace, + ); + const mutatorIcon = defBlock && defBlock.getIcon(Blockly.icons.MutatorIcon.TYPE); + const mutatorOpen = mutatorIcon && mutatorIcon.bubbleIsVisible(); + if (!mutatorOpen) { + this.quarkConnections_ = {}; + this.quarkIds_ = null; + } else { + // fix #6091 - this call could cause an error when outside if-else + // expanding block while mutating prevents another error (ancient fix) + this.setCollapsed(false); + } + // Test arguments (arrays of strings) for changes. '\n' is not a valid + // argument name character, so it is a valid delimiter here. + if (paramNames.join('\n') === this.arguments_.join('\n')) { + // No change. + this.quarkIds_ = paramIds; + return; + } + if (paramIds.length !== paramNames.length) { + throw Error('paramNames and paramIds must be the same length.'); + } + if (!this.quarkIds_) { + // Initialize tracking for this block. + this.quarkConnections_ = {}; + this.quarkIds_ = []; + } + // Update the quarkConnections_ with existing connections. + for (let i = 0; i < this.arguments_.length; i++) { + const input = this.getInput('ARG' + i); + if (input) { + const connection = input?.connection?.targetConnection; + this.quarkConnections_[this.quarkIds_[i]] = connection; + if ( + mutatorOpen && + connection && + !paramIds.includes(this.quarkIds_[i]) + ) { + // This connection should no longer be attached to this block. + connection.disconnect(); + connection.getSourceBlock().bumpNeighbours(); + } + } + } + // Rebuild the block's arguments. + this.arguments_ = [].concat(paramNames); + // And rebuild the argument model list. + this.argumentVarModels_ = []; + for (var i = 0; i < this.arguments_.length; i++) { + var variable = Blockly.Variables.getOrCreateVariablePackage( + this.workspace, null, this.arguments_[i], ''); + this.argumentVarModels_.push(variable); + } + + this.updateShape_(); + this.quarkIds_ = paramIds; + // Reconnect any child blocks. + if (this.quarkIds_) { + for (let i = 0; i < this.arguments_.length; i++) { + const quarkId = this.quarkIds_[i]; // TODO(#6920) + if (quarkId in this.quarkConnections_) { + // TODO(#6920): investigate claimed circular initialisers. + const connection = this.quarkConnections_[quarkId]; + if (!connection?.reconnect(this, 'ARG' + i)) { + // Block no longer exists or has been attached elsewhere. + delete this.quarkConnections_[quarkId]; + } + } + } + } + }, + /** + * Modify this block to have the correct number of arguments. + * @private + * @this {Blockly.Block} + */ + updateShape_: function () { + for (var i = 0; i < this.arguments_.length; i++) { + var field = this.getField('ARGNAME' + i); + if (field) { + // Ensure argument name is up to date. + // The argument name field is deterministic based on the mutation, + // no need to fire a change event. + Blockly.Events.disable(); + try { + field.setValue(this.arguments_[i]); + } finally { + Blockly.Events.enable(); + } + } else { + // Add new input. + field = new Blockly.FieldLabel(this.arguments_[i]); + var input = this.appendValueInput('ARG' + i) + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField(field, 'ARGNAME' + i); + input.init(); + } + } + // Remove deleted inputs. + while (this.getInput('ARG' + i)) { + this.removeInput('ARG' + i); + i++; + } + // Add 'with:' if there are parameters, remove otherwise. + var topRow = this.getInput('TOPROW'); + if (topRow) { + if (this.arguments_.length) { + if (!this.getField('WITH')) { + topRow.appendField(Blockly.Msg['PROCEDURES_CALL_BEFORE_PARAMS'], 'WITH'); + topRow.init(); + } + } else { + if (this.getField('WITH')) { + topRow.removeField('WITH'); + } + } + } + }, + /** + * Create XML to represent the (non-editable) name and arguments. + * @return {!Element} XML storage element. + * @this {Blockly.Block} + */ + mutationToDom: function () { + var container = Blockly.utils.xml.createElement('mutation'); + container.setAttribute('name', this.getProcedureCall()); + for (var i = 0; i < this.arguments_.length; i++) { + var parameter = Blockly.utils.xml.createElement('arg'); + parameter.setAttribute('name', this.arguments_[i]); + container.appendChild(parameter); + } + return container; + }, + /** + * Parse XML to restore the (non-editable) name and parameters. + * @param {!Element} xmlElement XML storage element. + * @this {Blockly.Block} + */ + domToMutation: function (xmlElement) { + var name = xmlElement.getAttribute('name'); + this.renameProcedure(this.getProcedureCall(), name); + var args = []; + var paramIds = []; + for (var i = 0, childNode; (childNode = xmlElement.childNodes[i]); i++) { + if (childNode.nodeName.toLowerCase() == 'arg') { + args.push(childNode.getAttribute('name')); + paramIds.push(childNode.getAttribute('paramId')); + } + } + this.setProcedureParameters_(args, paramIds); + }, + /** + * Returns the state of this block as a JSON serializable object. + * + * @returns The state of this block, ie the params and procedure name. + */ + saveExtraState: function () { + const state = Object.create(null); + state['name'] = this.getProcedureCall(); + if (this.arguments_.length) { + state['params'] = this.arguments_; + } + return state; + }, + /** + * Applies the given state to this block. + * + * @param state The state to apply to this block, ie the params and + * procedure name. + */ + loadExtraState: function (state) { + this.renameProcedure(this.getProcedureCall(), state['name']); + const params = state['params']; + if (params) { + const ids = []; + ids.length = params.length; + ids.fill(null); // TODO(#6920) + this.setProcedureParameters_(params, ids); + } + }, + /** + * Return all variables referenced by this block. + * @return {!Array} List of variable names. + * @this {Blockly.Block} + */ + getVars: function () { + return this.arguments_; + }, + /** + * Return all variables referenced by this block. + * @return {!Array} List of variable models. + * @this {Blockly.Block} + */ + getVarModels: function () { + return this.argumentVarModels_; + }, + /** + * Procedure calls cannot exist without the corresponding procedure + * definition. Enforce this link whenever an event is fired. + * @param {!Blockly.Events.Abstract} event Change event. + * @this {Blockly.Block} + */ + onchange: function (event) { + if (!this.workspace || this.workspace.isFlyout) { + // Block is deleted or is in a flyout. + return; + } + if (!event.recordUndo) { + // Events not generated by user. Skip handling. + return; + } + if (event.type == Blockly.Events.BLOCK_CREATE && + event.ids.indexOf(this.id) != -1) { + // Look for the case where a procedure call was created (usually through + // paste) and there is no matching definition. In this case, create + // an empty definition block with the correct signature. + var name = this.getProcedureCall(); + var def = Procedures.getDefinition(name, this.workspace); + if (def && (def.type != this.defType_)) { + // The signatures don't match. + def = null; + } + if (!def) { + Blockly.Events.setGroup(event.group); + /** + * Create matching definition block. + * + * + * + * + * + * test + * + * + */ + var xml = Blockly.utils.xml.createElement('xml'); + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', this.defType_); + var xy = this.getRelativeToSurfaceXY(); + var x = xy.x + Blockly.SNAP_RADIUS * (this.RTL ? -1 : 1); + var y = xy.y + Blockly.SNAP_RADIUS * 2; + block.setAttribute('x', x); + block.setAttribute('y', y); + var mutation = this.mutationToDom(); + block.appendChild(mutation); + var field = Blockly.utils.xml.createElement('field'); + field.setAttribute('name', 'NAME'); + var callName = this.getProcedureCall(); + if (!callName) { + // Rename if name is empty string. + callName = Procedures.findLegalName('', this); + this.renameProcedure('', callName); + } + field.appendChild(Blockly.utils.xml.createTextNode(callName)); + block.appendChild(field); + xml.appendChild(block); + Blockly.Xml.domToWorkspace(xml, this.workspace); + Blockly.Events.setGroup(false); + } else { + if (JSON.stringify(def.getVars()) != JSON.stringify(this.arguments_)) { + let paramNames = def.arguments_; + let paramIds = []; + for (var i = 0; i < this.arguments_.length; i++) { + var input = this.getInput('ARG' + i); + if (!input) { + continue; + } + var connection = input.connection.targetConnection; + if (!connection) { + paramIds.push(null); + continue; + } + paramIds.push(connection.sourceBlock_.id); + } + this.setProcedureParameters_(paramNames, paramIds); + } + } + } else if (event.type == Blockly.Events.BLOCK_DELETE) { + // Look for the case where a procedure definition has been deleted, + // leaving this block (a procedure call) orphaned. In this case, delete + // the orphan. + var name = this.getProcedureCall(); + var def = Procedures.getDefinition(name, this.workspace); + if (!def) { + Blockly.Events.setGroup(event.group); + this.dispose(true); + Blockly.Events.setGroup(false); + } + } else if (event.type == Blockly.Events.CHANGE && event.element == 'disabled') { + var name = this.getProcedureCall(); + var def = Procedures.getDefinition(name, this.workspace); + if (def && def.id == event.blockId) { + // in most cases the old group should be '' + var oldGroup = Blockly.Events.getGroup(); + if (oldGroup) { + // This should only be possible programmatically and may indicate a problem + // with event grouping. If you see this message please investigate. If the + // use ends up being valid we may need to reorder events in the undo stack. + console.log('Saw an existing group while responding to a definition change'); + } + Blockly.Events.setGroup(event.group); + if (event.newValue) { + this.previousEnabledState_ = this.isEnabled(); + this.setEnabled(false); + } else { + this.setEnabled(this.previousEnabledState_); + } + Blockly.Events.setGroup(oldGroup); + } + } + }, + /** + * Add menu option to find the definition block for this call. + * @param {!Array} options List of menu options to add to. + * @this {Blockly.Block} + */ + customContextMenu: function (options) { + if (!this.workspace.isMovable()) { + // If we center on the block and the workspace isn't movable we could + // loose blocks at the edges of the workspace. + return; + } + + var option = { enabled: true }; + option.text = Blockly.Msg['PROCEDURES_HIGHLIGHT_DEF']; + var name = this.getProcedureCall(); + var workspace = this.workspace; + option.callback = function () { + var def = Procedures.getDefinition(name, workspace); + if (def) { + workspace.centerOnBlock(def.id); + def.select(); + } + }; + options.push(option); + }, + defType_: 'procedures_defnoreturn' +}; + +export const procedures_callreturn = { + /** + * Block for calling a procedure with a return value. + * @this {Blockly.Block} + */ + init: function () { + this.appendDummyInput('TOPROW') + .appendField('', 'NAME'); + this.setOutput(true); + this.setStyle('procedure_blocks'); + // Tooltip is set in domToMutation. + this.setHelpUrl(Blockly.Msg['PROCEDURES_CALLRETURN_HELPURL']); + this.arguments_ = []; + this.argumentVarModels_ = []; + this.quarkConnections_ = {}; + this.quarkIds_ = null; + this.previousEnabledState_ = true; + }, + + getProcedureCall: procedures_callnoreturn.getProcedureCall, + renameProcedure: procedures_callnoreturn.renameProcedure, + setProcedureParameters_: + procedures_callnoreturn.setProcedureParameters_, + updateShape_: procedures_callnoreturn.updateShape_, + mutationToDom: procedures_callnoreturn.mutationToDom, + domToMutation: procedures_callnoreturn.domToMutation, + getVars: procedures_callnoreturn.getVars, + getVarModels: procedures_callnoreturn.getVarModels, + onchange: procedures_callnoreturn.onchange, + customContextMenu: + procedures_callnoreturn.customContextMenu, + defType_: 'procedures_defreturn' +}; + +export const procedures_ifreturn = { + /** + * Block for conditionally returning a value from a procedure. + * @this {Blockly.Block} + */ + init: function () { + this.appendValueInput('CONDITION') + .setCheck('Boolean') + .appendField(Blockly.Msg['CONTROLS_IF_MSG_IF']); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setStyle('procedure_blocks'); + this.setTooltip(Blockly.Msg['PROCEDURES_IFRETURN_TOOLTIP']); + this.setHelpUrl(Blockly.Msg['PROCEDURES_IFRETURN_HELPURL']); + this.hasReturnValue_ = true; + }, + /** + * Create XML to represent whether this block has a return value. + * @return {!Element} XML storage element. + * @this {Blockly.Block} + */ + mutationToDom: function () { + var container = Blockly.utils.xml.createElement('mutation'); + container.setAttribute('value', Number(this.hasReturnValue_)); + return container; + }, + /** + * Parse XML to restore whether this block has a return value. + * @param {!Element} xmlElement XML storage element. + * @this {Blockly.Block} + */ + domToMutation: function (xmlElement) { + var value = xmlElement.getAttribute('value'); + this.hasReturnValue_ = (value == 1); + if (!this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']); + } + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if this flow block is not nested inside a loop. + * @param {!Blockly.Events.Abstract} _e Change event. + * @this {Blockly.Block} + */ + onchange: function () { + if (!this.workspace.isDragging || this.workspace.isDragging()) { + return; // Don't change state at the start of a drag. + } + var legal = false; + // Is the block nested in a procedure? + var block = this; + do { + if (this.FUNCTION_TYPES.indexOf(block.type) != -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + // If needed, toggle whether this block has a return value. + if (block.type == 'procedures_defnoreturn' && this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']); + this.hasReturnValue_ = false; + } else if (block.type == 'procedures_defreturn' && + !this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg['PROCEDURES_DEFRETURN_RETURN']); + this.hasReturnValue_ = true; + } + this.setWarningText(null); + if (!this.isInFlyout) { + this.setEnabled(true); + } + } else { + this.setWarningText(Blockly.Msg['PROCEDURES_IFRETURN_WARNING']); + if (!this.isInFlyout && !this.getInheritedDisabled()) { + this.setEnabled(false); + } + } + }, + /** + * List of block types that are functions and thus do not need warnings. + * To add a new function type add this to your code: + * procedures_ifreturn.FUNCTION_TYPES.push('custom_func'); + */ + FUNCTION_TYPES: ['procedures_defnoreturn', 'procedures_defreturn'] +}; + +export const procedures_return = { + /** + * Block for conditionally returning a value from a procedure. + * @this Blockly.Block + */ + init: function () { + this.setStyle('procedure_blocks'); + // this.appendValueInput('CONDITION') + // .setCheck(Boolean) + // .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP); + this.hasReturnValue_ = true; + }, + /** + * Create XML to represent whether this block has a return value. + * @return {!Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('value', Number(this.hasReturnValue_)); + return container; + }, + /** + * Parse XML to restore whether this block has a return value. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var value = xmlElement.getAttribute('value'); + this.hasReturnValue_ = (value == 1); + if (!this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + } + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if this flow block is not nested inside a loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function () { + var legal = false; + // Is the block nested in a procedure? + var block = this; + do { + if (this.FUNCTION_TYPES.indexOf(block.type) != -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + // If needed, toggle whether this block has a return value. + if (block.type == 'procedures_defnoreturn' && this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendDummyInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = false; + } else if (block.type == 'procedures_defreturn' && + !this.hasReturnValue_) { + this.removeInput('VALUE'); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN); + this.hasReturnValue_ = true; + } + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING); + } + }, + /** + * List of block types that are functions and thus do not need warnings. + * To add a new function type add this to your code: + * procedures_ifreturn.FUNCTION_TYPES.push('custom_func'); + */ + FUNCTION_TYPES: ['procedures_defnoreturn', 'procedures_defreturn', 'method_procedures_defnoreturn', 'method_procedures_defreturn'] +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/set.js b/mixly/boards/default_src/python/blocks/set.js new file mode 100644 index 00000000..71267c7a --- /dev/null +++ b/mixly/boards/default_src/python/blocks/set.js @@ -0,0 +1,414 @@ +import * as Blockly from 'blockly/core'; + +const SET_HUE = 100; + +export const set_create_with = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(SET_HUE); + this.appendDummyInput("") + //don't need to specify the data type in Python + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'Array'], [Blockly.Msg.LANG_MATH_STRING, 'Array'], [Blockly.Msg.LANG_MATH_BOOLEAN, 'Array']]), 'TYPE') + // .appendField(' ') + .appendField(new Blockly.FieldTextInput('s1'), 'VAR') + + this.itemCount_ = 3; + this.updateShape_(); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['set_create_with_item'], this)); + this.setTooltip(Blockly.Msg.blockpy_SET_CREATE_WITH_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('set_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('set_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.blockpy_SET_CREATE_EMPTY_TITLE); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.blockpy_SET_CREATE_WITH_INPUT_WITH); + } + } + } + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const set_create_with_container = { + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(SET_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const set_create_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(SET_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_SET_VARIABLES_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.blockpy_SET_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const set_length = { + + init: function () { + this.setColour(SET_HUE); + this.appendValueInput('SET'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LENGTH); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.SET_LENGTH_TOOLTIP); + this.setOutput(true, Number); + } +}; + +export const set_pop = { + init: function () { + this.setColour(SET_HUE); + this.appendValueInput('SET') + .setCheck('Set') + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_SET_GET_AND_REMOVE_LAST); + this.setTooltip(Blockly.Msg.SET_POP_TOOLTIP); + this.setInputsInline(true); + this.setOutput(true); + } +}; + +export const set_clear = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(SET_HUE); + this.appendValueInput('SET') + .setCheck('Set') + this.appendDummyInput("") + .appendField(Blockly.Msg.SET_CLEAR); + + this.setPreviousStatement(true); + this.setNextStatement(true); + } +}; + +export const set_operate = { + init: function () { + + + this.appendValueInput('SET1') + .setCheck('Set') + var operate = [ + [Blockly.Msg.blockpy_set_union, 'union'], + [Blockly.Msg.blockpy_set_intersection, 'intersection'], + [Blockly.Msg.blockpy_set_difference, 'difference'] + ]; + this.setColour(SET_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_and_set) + this.appendValueInput('SET2') + .setCheck('Set') + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_get_operate) + .appendField(new Blockly.FieldDropdown(operate), 'OPERATE') + + this.setInputsInline(true); + this.setOutput(true, "set"); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OPERATE'); + var TOOLTIPS = { + 'union': Blockly.Msg.MIXLY_TOOLTIP_SET_UNION, + 'intersection': Blockly.Msg.MIXLY_TOOLTIP_SET_INTERSECTION, + 'difference': Blockly.Msg.MIXLY_TOOLTIP_SET_DIFFERENCE + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const set_operate_update = { + init: function () { + + this.appendValueInput('SET1') + .setCheck('Set') + var operate_update = [ + [Blockly.Msg.blockpy_set_union, 'update'], + [Blockly.Msg.blockpy_set_intersection, 'intersection_update'], + [Blockly.Msg.blockpy_set_difference, 'difference_update'] + ]; + this.setColour(SET_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_and_set) + this.appendValueInput('SET2') + .setCheck('Set') + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_get_operate) + .appendField(new Blockly.FieldDropdown(operate_update), 'OPERATE') + + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_update) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OPERATE'); + var TOOLTIPS = { + 'update': Blockly.Msg.MIXLY_TOOLTIP_SET_UPDATE, + 'intersection_update': Blockly.Msg.MIXLY_TOOLTIP_SET_INTERSECTION_UPDATE, + 'difference_update': Blockly.Msg.MIXLY_TOOLTIP_SET_DIFFERENCE_UPDATE + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const set_add_discard = { + init: function () { + this.appendValueInput('SET') + .setCheck('Set') + var changenum = + [[Blockly.Msg.MIXLY_blockpy_set_add, 'add'], [Blockly.Msg.MIXLY_blockpy_set_discard, 'discard']]; + this.setColour(SET_HUE); + this.appendDummyInput("") + .appendField(new Blockly.FieldDropdown(changenum), 'OPERATE') + this.appendValueInput('data') + .appendField(Blockly.Msg.blockpy_SET_VARIABLES_NAME) + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OPERATE'); + var TOOLTIPS = { + 'add': Blockly.Msg.SET_ADD_TOOLTIP, + 'discard': Blockly.Msg.SET_DISCARD_TOOLTIP, + + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const set_sub = { + init: function () { + + this.appendValueInput('SET1') + .setCheck('Set') + var sub_super = [ + [Blockly.Msg.blockpy_set_sub, 'issubset'], + [Blockly.Msg.blockpy_set_super, 'issuperset'] + ]; + this.setColour(SET_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_is_set) + this.appendValueInput('SET2') + .setCheck('Set') + this.appendDummyInput("") + .appendField(Blockly.Msg.blockpy_set_of) + .appendField(new Blockly.FieldDropdown(sub_super), 'OPERATE') + + + this.setInputsInline(true); + this.setOutput(true, Boolean); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OPERATE'); + var TOOLTIPS = { + 'issubset': Blockly.Msg.MIXLY_TOOLTIP_SET_SUB, + 'issuperset': Blockly.Msg.MIXLY_TOOLTIP_SET_SUPER + + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const set_update = { + init: function () { + this.appendValueInput('SET') + .setCheck('Set') + this.setColour(SET_HUE); + this.appendValueInput('VAR') + .setCheck([String, 'List']) + .appendField(Blockly.Msg.blockpy_set_add_update); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.SET_UPDATE_TOOLTIP); + } +}; + +// export const set_change_to = { +// init: function() { +// var OPERATORS = +// [[Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, 'list'], +// [Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, 'tuple'] +// ]; +// this.setColour(SET_HUE); +// this.appendValueInput('VAR') +// .setCheck("Set") +// // .appendField(Blockly.Msg.blockpy_USE_LIST); +// this.appendDummyInput("") +// .appendField(Blockly.Msg.A_TO_B) +// .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); +// this.setInputsInline(true); +// this.setOutput(true); +// var thisBlock = this; +// this.setTooltip(function() { +// var mode = thisBlock.getFieldValue('OP'); +// var TOOLTIPS = { +// 'list': Blockly.Msg.SET_TO_LISTS, +// 'tuple': Blockly.Msg.SET_TO_TUPLE, +// }; +// return TOOLTIPS[mode]; +// }); +// } +// }; + +export const set_create_with_text_return = { + init: function () { + this.setColour(SET_HUE); + this.appendDummyInput("") + .appendField('{') + .appendField(new Blockly.FieldTextInput('0,0,0'), 'TEXT') + .appendField('}'); + // .appendField(this.newQuote_(false)) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXPY_TOOLTIP_SET_CREATE_WITH_TEXT); + } +} + +export const set_toset = { + init: function () { + this.setColour(SET_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_TOSET); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOSET); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/storage.js b/mixly/boards/default_src/python/blocks/storage.js new file mode 100644 index 00000000..70e932ef --- /dev/null +++ b/mixly/boards/default_src/python/blocks/storage.js @@ -0,0 +1,519 @@ +import * as Blockly from 'blockly/core'; + +const STORAGE_HUE = 0; //'#5d69c5'//0; + +export const storage_open_file_with_os = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput('fn') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_PYTHON_STORAGE_OPEN_FILE_WITH_OS + "(For Windows)"); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + } +} + +export const storage_fileopen = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILENAME") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_OPEN_FILE); + //.appendField(new Blockly.FieldTextInput('filename.txt'), 'FILENAME'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_READ, 'r'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_WRITE, 'w'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_READ, 'rb'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_WRITE, 'wb'], + [Blockly.Msg.MIXLY_ADD, 'a'], + [Blockly.Msg.MATH_BIN + Blockly.Msg.MIXLY_ADD, 'ab'], + [Blockly.Msg.MIXLY_R_W ,'r+'], + [Blockly.Msg.MATH_BIN + Blockly.Msg.MIXLY_R_W ,'rb+'], + [Blockly.Msg.MIXLY_W_R ,'w+'], + [Blockly.Msg.MATH_BIN + Blockly.Msg.MIXLY_W_R ,'wb+'], + [Blockly.Msg.MIXLY_A_R ,'a+'], + [Blockly.Msg.MATH_BIN + Blockly.Msg.MIXLY_A_R ,'ab+'] + ]), 'MODE'); + this.appendValueInput("FILE") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_AS); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.MIXLY_USE; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_OPEN_FILE; + var mode3 = Blockly.Msg.MIXLY_BELONG; + var TOOLTIPS = { + 'r': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_READ, + 'w': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_WRITE, + 'rb': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_READ, + 'wb': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_WRITE + }; + return mode0 + TOOLTIPS[mode] + mode3 + mode1 + mode2; + }); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + + +export const storage_fileopen_new = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILENAME") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_OPEN_FILE); + //.appendField(new Blockly.FieldTextInput('filename.txt'), 'FILENAME'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_READ, 'r'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_WRITE, 'w'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_READ, 'rb'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_WRITE, 'wb'] + ]), 'MODE'); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.MIXLY_USE; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_OPEN_FILE; + var mode3 = Blockly.Msg.MIXLY_BELONG; + var mode4 = Blockly.Msg.PY_STORAGE_FILE_OBJECT; + var TOOLTIPS = { + 'r': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_READ, + 'w': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_WRITE, + 'rb': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_READ, + 'wb': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_WRITE + }; + return mode0 + TOOLTIPS[mode] + mode3 + mode1 + mode2 + mode4; + }); + } +}; + +export const storage_fileopen_new_encoding = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILENAME") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_OPEN_FILE); + //.appendField(new Blockly.FieldTextInput('filename.txt'), 'FILENAME'); + var code = + [['ANSI', 'ANSI'], ['gbk', 'gbk'], ['utf-8', 'utf-8']]; + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_READ, 'r'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_WRITE, 'w'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_READ, 'rb'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_WRITE, 'wb'] + ]), 'MODE'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXPY_TEXT_ENCODE) + .appendField(new Blockly.FieldDropdown(code), 'CODE') + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.MIXLY_USE; + var mode1 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MODE; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_OPEN_FILE; + var mode3 = Blockly.Msg.MIXLY_BELONG; + var mode4 = Blockly.Msg.PY_STORAGE_FILE_OBJECT; + var TOOLTIPS = { + 'r': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_READ, + 'w': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_WRITE, + 'rb': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_READ, + 'wb': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_BIT_WRITE + }; + return mode0 + TOOLTIPS[mode] + mode3 + mode1 + mode2 + mode4; + }); + } +}; + +export const storage_file_write = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput('data') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE); + this.appendValueInput("FILE") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_WRITE); + // .appendField(new Blockly.FieldTextInput('f'), 'FILE'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE + Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_WRITE); + } +} + +export const storage_get_contents_without_para = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck('Variable') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FROM_FILE); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ALL, 'read'], [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ONE_LINE, 'readline'], [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ALL_LINES, 'readlines']]), 'MODE'); + this.setInputsInline(true); + this.setPreviousStatement(false); //in front of the block has something + this.setNextStatement(false); //beyond the ... has something + this.setOutput(true, String); + } +}; + +export const storage_get_contents = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck('Variable') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FROM_FILE); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_NO_MORE_THAN_SIZE, 'read'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ONE_LINE_NO_MORE_THAN_SIZE, 'readline'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ALL_LINES_NO_MORE_THAN_SIZE, 'readlines'] + ]), 'MODE'); + this.appendValueInput("SIZE") + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHARACTER); + this.setInputsInline(true); + this.setPreviousStatement(false); //in front of the block has something + this.setNextStatement(false); //beyond the ... has something + this.setOutput(true, String); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FROM_FILE; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHARACTER; + var TOOLTIPS = { + 'read': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_NO_MORE_THAN_SIZE, + 'readline': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ONE_LINE_NO_MORE_THAN_SIZE, + 'readlines': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ALL_LINES_NO_MORE_THAN_SIZE + }; + return mode0 + TOOLTIPS[mode] + 'x' + mode2; + }); + } +}; + +export const storage_get_a_line = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FROM_FILE); + this.setNextStatement(true); + this.appendValueInput("SIZE") + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_ONE_LINE_NO_MORE_THAN_SIZE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHARACTER); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MICROBIT_PYTHON_TYPE); + } +}; + +export const storage_can_write_ornot = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .appendField(Blockly.Msg.HTML_FILE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CAN_WRITE_ORNOT); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, Boolean); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CAN_WRITE_ORNOT1); + } +}; + +export const storage_get_filename = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILENAME); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET_FILENAME); + } +}; + +export const storage_close_file = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CLOSE_FILE); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setOutput(false); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CLOSE_FILE); + } +}; + +export const storage_list_all_files = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_LIST_ALL_FILES); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, 'List'); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_LIST_ALL_FILES); + } +}; +Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_DELETE_FILE +export const storage_delete_file = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_DELETE_FILE, 'remove'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_DELETE_DIRS, 'removedirs'] + ]), 'MODE'); + this.appendValueInput("FILE") + .setCheck(String); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setOutput(false); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_DELETE_FILE); + } +}; + +export const storage_get_file_size = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET_FILE_SIZE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_SIZE); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET_FILE_SIZE + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_SIZE); + } +}; + +export const storage_file_tell = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_RETURN_FILE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_PRESENT_LOCATION); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_TELL); + } +}; + +export const storage_file_seek = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck('Variable') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_SET_FILE_POSITION); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CURRENT_POSITION); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_START, 'start'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_CURRENT, 'current'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_END, 'end'] + ]), 'MODE'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_OFFSET); + this.appendValueInput("SIZE") + .setCheck(Number); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHARACTER); + this.setInputsInline(true); + this.setPreviousStatement(true); //in front of the block has something + this.setNextStatement(true); //beyond the ... has something + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_SET_FILE_POSITION + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CURRENT_POSITION; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHARACTER; + var mode3 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_OFFSET; + var TOOLTIPS = { + 'start': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_START, + 'current': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_CURRENT, + 'end': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_FILE_SEEK_END + }; + return mode0 + " " + TOOLTIPS[mode] + mode3 + 'x' + mode2; + }); + } +}; + +export const storage_get_current_dir = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET_CURRENT_DIR); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, 'List'); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET_CURRENT_DIR); + } +}; + +export const storage_make_dir = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("PATH") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_PATH); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_ESP32_SET); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MKDIR, 'mkdir'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MAKEDIRS, 'makedirs'] + ]), 'MODE'); + this.setInputsInline(true); + this.setPreviousStatement(true); //in front of the block has something + this.setNextStatement(true); //beyond the ... has something + this.setOutput(false); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_PATH; + var mode2 = Blockly.Msg.MIXLY_ESP32_SET; + var TOOLTIPS = { + 'mkdir': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MKDIR, + 'makedirs': Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKEDIRS + }; + return mode0 + 'x' + mode2 + TOOLTIPS[mode]; + }); + } +}; + +export const storage_rename = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_RENAME); + this.appendValueInput("NEWFILE") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_AS); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setOutput(false); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_RENAME); + } +}; + +export const storage_change_dir = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHANGE_DIR); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setOutput(false); + this.setTooltip(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHANGE_DIR); + } +}; + +export const storage_is_file = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput("FILE") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_IS_OR_NOT); + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.HTML_FILE, 'isfile'], + [Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_IS_DIR, 'isdir'] + ]), 'MODE'); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, Boolean); + let thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('MODE'); + var mode0 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_THE_PATH; + var mode2 = Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_IS_OR_NOT; + var TOOLTIPS = { + 'isfile': Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_MKDIR, + 'isdir': Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKEDIRS + }; + return mode0 + 'x' + mode2 + TOOLTIPS[mode]; + }); + } +}; + +export const sdcard_use_spi_init = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput('SPISUB') + .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH + "SPI") + .setCheck("var"); + this.appendValueInput('PINSUB') + .appendField("CS") + this.appendValueInput('SUB') + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_SOCKET_MAKE) + .setCheck("var"); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_SETUP + Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .appendField(Blockly.Msg.MIXLY_SD_CARD); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +export const sdcard_mount = { + init: function () { + this.setColour(STORAGE_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_SD_CARD); + this.appendValueInput("DIR") + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_SDCARD_MOUNT); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setInputsInline(true); + this.setTooltip(); + } +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/text.js b/mixly/boards/default_src/python/blocks/text.js new file mode 100644 index 00000000..eadbb6f3 --- /dev/null +++ b/mixly/boards/default_src/python/blocks/text.js @@ -0,0 +1,999 @@ +import * as Blockly from 'blockly/core'; + +const TEXTS_HUE = 160//'#9ec440'//160; + +export const text = { + /** + * Block for text value. + * @this Blockly.Block + */ + init: function () { + //this.setHelpUrl(Blockly.Msg.TEXT_TEXT_HELPURL); + this.setColour(TEXTS_HUE); + this.appendDummyInput() + .appendField(this.newQuote_(true)) + .appendField(new Blockly.FieldTextInput(''), 'TEXT') + .appendField(this.newQuote_(false)); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.TEXT_TEXT_TOOLTIP); + }, + /** + * Create an image of an open or closed quote. + * @param {boolean} open True if open quote, false if closed. + * @return {!Blockly.FieldImage} The field image of the quote. + * @private + */ + newQuote_: function (open) { + if (open == this.RTL) { + var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAqUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhggONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvBO3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5AoslLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg=='; + } else { + var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAn0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMfz9AylsaRRgGzvZAAAAAElFTkSuQmCC'; + } + return new Blockly.FieldImage(file, 12, 12, '"'); + } +}; + +export const text_textarea = { + /** + * Block for text value. + * @this Blockly.Block + */ + init: function () { + //this.setHelpUrl(Blockly.Msg.TEXT_TEXT_HELPURL); + this.setColour(TEXTS_HUE); + this.appendDummyInput() + .appendField(this.newQuote_(true)) + .appendField(new Blockly.FieldMultilineInput('Hello\nMixly'), 'VALUE') + // .appendField(new Blockly.FieldTextInput(''), 'TEXT') + .appendField(this.newQuote_(false)); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.TEXT_LINES_TOOLTIP); + }, + /** + * Create an image of an open or closed quote. + * @param {boolean} open True if open quote, false if closed. + * @return {!Blockly.FieldImage} The field image of the quote. + * @private + */ + newQuote_: function (open) { + if (open == this.RTL) { + var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAqUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhggONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvBO3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5AoslLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg=='; + } else { + var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAn0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMfz9AylsaRRgGzvZAAAAAElFTkSuQmCC'; + } + return new Blockly.FieldImage(file, 12, 12, '"'); + } +}; + +export const text_bytes = { + /** + * Block for text value. + * @this Blockly.Block + */ + init: function () { + this.setColour(TEXTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_TEXT_BYTES) + .appendField(this.newQuote_(true)) + .appendField(new Blockly.FieldTextInput(''), 'TEXT') + .appendField(this.newQuote_(false)); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.TEXT_TEXT_TOOLTIP); + }, + /** + * Create an image of an open or closed quote. + * @param {boolean} open True if open quote, false if closed. + * @return {!Blockly.FieldImage} The field image of the quote. + * @private + */ + newQuote_: function (open) { + if (open == this.RTL) { + var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAqUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhggONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvBO3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5AoslLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg=='; + } else { + var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAn0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMfz9AylsaRRgGzvZAAAAAElFTkSuQmCC'; + } + return new Blockly.FieldImage(file, 12, 12, '"'); + } +}; + +Blockly.FieldTextInput.char_validator = function (text) { + if (text.length > 1) { + if (text.charAt(0) === "\\") { + var charAtOne = text.charAt(1); + if (charAtOne === "0" || + charAtOne === "b" || + charAtOne === "f" || + charAtOne === "n" || + charAtOne === "r" || + charAtOne === "t" || + charAtOne === "\\" || + charAtOne === "'") { + return String(text).substring(0, 2); + } else if (charAtOne === "x" && text.charAt(2) === "0" && text.charAt(3) === "B") { + return String(text).substring(0, 4); + } + } + } + return String(text).substring(0, 1); +}; + +export const text_char = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendDummyInput() + .appendField(this.newQuote_(true)) + .appendField(new Blockly.FieldTextInput('', Blockly.FieldTextInput.char_validator), 'TEXT') + .appendField(this.newQuote_(false)); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.TEXT_CHAR_TOOLTIP); + }, + newQuote_: function (open) { + if (open == true) { + var file = '../../media/quote2.png'; + } else { + var file = '../../media/quote3.png'; + } + return new Blockly.FieldImage(file, 7, 12, '"'); + } +}; + + +export const text_join = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput('A') + .setCheck([String, Number]); + this.appendValueInput('B') + .setCheck([String, Number]) + .appendField(Blockly.Msg.MIXLY_TEXT_JOIN); + this.setInputsInline(true); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_TEXT_JOIN); + } +}; + +export const ascii_to_char = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput('VAR') + .setCheck(Number) + .appendField(Blockly.Msg.MIXLY_TOCHAR); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_TEXT_TOCHAR); + } +}; + +export const char_to_ascii = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput('VAR') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_TOASCII); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_TEXT_TOASCII); + } +}; + +export const number_to_text = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_TOSTRING); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOTEXT); + } +}; + +export const text_length = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_LENGTH); + this.setOutput(true, Number); + this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_TEXT_LENGTH); + } +} + + + +export const text_char_at2 = { + init: function () { + this.WHERE_OPTIONS = [ + [Blockly.Msg.LISTS_GET_INDEX_FROM_START, "FROM_START"], + [Blockly.Msg.LISTS_GET_INDEX_FROM_END, "FROM_END"], + [Blockly.Msg.TEXT_GET_INDEX_RANDOM + 1 + Blockly.Msg.TEXT_CHARAT2, "RANDOM"] + ]; + this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL); + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .setCheck(String) + // .appendField(Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST) + this.appendValueInput("AT") + .setCheck(Number) + this.appendDummyInput() + //.appendField(Blockly.Msg.MIXLY_MID) + .appendField(Blockly.Msg.LISTS_GET_INDEX_GET, "MODE"); + // .appendField("", "SPACE"); + Blockly.Msg.LISTS_GET_INDEX_TAIL && this.appendDummyInput("TAIL").appendField(Blockly.Msg.LISTS_GET_INDEX_TAIL); + // this.appendDummyInput().appendField(Blockly.Msg.MIXLY_DE); + this.setInputsInline(!0); + this.setOutput(!0); + this.updateAt_(!0); + var b = this; + this.setTooltip(function () { + var a = b.getFieldValue("MODE"), + e = b.getFieldValue("WHERE"), + d = ""; + switch (a + " " + e) { + case "GET FROM_START": + case "GET FROM_END": + d = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM; + break; + case "GET RANDOM": + d = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM; + break; + case "GET_REMOVE FROM_START": + case "GET_REMOVE FROM_END": + d = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM; + break; + case "GET_REMOVE RANDOM": + d = Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM; + break; + } + if ("FROM_START" == e || "FROM_END" == e) d += " " + Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP.replace("%1", Blockly.Msg.ONE_BASED_INDEXING ? "#1" : "#0"); + return d + }) + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('WHERE'); + var TOOLTIPS = { + 'FROM_START': Blockly.Msg.LISTS_GET_INDEX_FROM_START, + 'FROM_END': Blockly.Msg.LISTS_GET_INDEX_FROM_END, + 'RANDOM': Blockly.Msg.TEXT_GET_INDEX_RANDOM + }; + return Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING + TOOLTIPS[mode] + 'n' + Blockly.Msg.TEXT_CHARAT2; + }); + }, + mutationToDom: function () { + var a = document.createElement("mutation"); + a.setAttribute("statement", !this.outputConnection); + var b = this.getInput("AT").type == Blockly.INPUT_VALUE; + a.setAttribute("at", b); + return a + }, + domToMutation: function (a) { + var b = "true" == a.getAttribute("statement"); + this.updateStatement_(b); + a = "false" != a.getAttribute("at"); + this.updateAt_(a) + }, + updateStatement_: function (a) { + a != !this.outputConnection && (this.unplug(!0, !0), a ? (this.setOutput(!1), this.setPreviousStatement(!0), this.setNextStatement(!0)) : (this.setPreviousStatement(!1), this.setNextStatement(!1), this.setOutput(!0))) + }, + updateAt_: function (a) { + this.removeInput("AT"); + this.removeInput("ORDINAL", !0); + a ? (this.appendValueInput("AT").setCheck(Number), Blockly.Msg.TEXT_CHARAT2 && this.appendDummyInput("ORDINAL").appendField(Blockly.Msg.TEXT_CHARAT2)) : this.appendDummyInput("AT"); + var b = new Blockly.FieldDropdown(this.WHERE_OPTIONS, + function (b) { + var e = "FROM_START" == b || "FROM_END" == b; + if (e != a) { + var d = this.sourceBlock_; + d.updateAt_(e); + d.setFieldValue(b, "WHERE"); + return null + } + }); + this.getInput("AT").appendField(b, "WHERE"); + Blockly.Msg.LISTS_GET_INDEX_TAIL && this.moveInputBefore("TAIL", null) + } +}; + + +export const text_char_at = { + init: function () { + this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL); + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .setCheck(String); + this.appendValueInput("AT") + .setCheck(Number) + .appendField(Blockly.Msg.LISTS_GET_INDEX_GET + " " + Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_CHARAT2); + this.setOutput(true); + this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN + Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING + Blockly.Msg.LISTS_GET_INDEX_FROM_START + 'n' + Blockly.Msg.TEXT_CHARAT2); + } +} + + +export const text_random_char = { + init: function () { + this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL); + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .setCheck(String); + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_RANDOM_CHAR); + this.setOutput(true); + this.setTooltip(Blockly.Msg.TEXT_RANDOM_CHAR_TOOLTIP); + } +} + + +export const text_substring2 = { + /** + * Block for getting sublist. + * @this Blockly.Block + */ + init: function () { + this['WHERE_OPTIONS_1'] = [ + [Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST, 'FIRST'] + ]; + this['WHERE_OPTIONS_2'] = [ + [Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_SUBLIST_END_LAST, 'LAST'] + ]; + this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL); + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .setCheck(String) + //.appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL) + // if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) { + // this.appendDummyInput('TAIL') + // .appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL); + // } + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendDummyInput('AT1'); + this.appendDummyInput('AT2'); + this.setInputsInline(true); + this.setOutput(true, 'List'); + this.updateAt_(1, true); + this.updateAt_(2, true); + this.setTooltip(Blockly.Msg._GET_TEXT_SUBLIST_TOOLTIP); + }, + /** + * Create XML to represent whether there are 'AT' inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + var isAt1 = this.getInput('AT1').type == Blockly.INPUT_VALUE; + container.setAttribute('at1', isAt1); + var isAt2 = this.getInput('AT2').type == Blockly.INPUT_VALUE; + container.setAttribute('at2', isAt2); + return container; + }, + /** + * Parse XML to restore the 'AT' inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var isAt1 = (xmlElement.getAttribute('at1') == 'true'); + var isAt2 = (xmlElement.getAttribute('at2') == 'true'); + this.updateAt_(1, isAt1); + this.updateAt_(2, isAt2); + }, + /** + * Create or delete an input for a numeric index. + * This block has two such inputs, independant of each other. + * @param {number} n Specify first or second input (1 or 2). + * @param {boolean} isAt True if the input should exist. + * @private + * @this Blockly.Block + */ + updateAt_: function (n, isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' inputs. + this.removeInput('AT' + n); + this.removeInput('ORDINAL' + n, true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT' + n).setCheck(Number); + if (Blockly.Msg.TEXT_CHARAT2) { + this.appendDummyInput('ORDINAL' + n) + .appendField(Blockly.Msg.TEXT_CHARAT2); + } + } else { + this.appendDummyInput('AT' + n); + } + var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n], + function (value) { + var newAt = (value == 'FROM_START') || (value == 'FROM_END'); + // The 'isAt' variable is available due to this function being a + // closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt_(n, newAt); + // This menu has been destroyed and replaced. + // Update the replacement. + block.setFieldValue(value, 'WHERE' + n); + return null; + } + return undefined; + }); + this.getInput('AT' + n) + .appendField(menu, 'WHERE' + n); + if (n == 1) { + this.moveInputBefore('AT1', 'AT2'); + if (this.getInput('ORDINAL1')) { + this.moveInputBefore('ORDINAL1', 'AT2'); + } + } + // if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) { + // this.moveInputBefore('TAIL', null); + // } + } +}; + +export const text_substring = { + /** + * Block for getting sublist. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL); + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .setCheck(String) + this.appendValueInput('AT1') + .appendField(Blockly.Msg.LISTS_GET_INDEX_GET + " " + Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendValueInput('AT2') + .appendField(Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_CHARAT2); + this.setInputsInline(true); + this.setOutput(true, ['List', String]); + this.setTooltip(Blockly.Msg._GET_TEXT_SUBLIST_TOOLTIP); + } +} + +export const text_equals_starts_ends = { + init: function () { + var TEXT_DOWHAT = [ + [Blockly.Msg.MIXLY_EQUALS, '==='], + [Blockly.Msg.MIXLY_STARTSWITH, 'startswith'], + [Blockly.Msg.MIXLY_ENDSWITH, 'endswith'] + ]; + this.setColour(TEXTS_HUE); + this.appendValueInput("STR1") + .setCheck(String); + this.appendValueInput("STR2") + .appendField(new Blockly.FieldDropdown(TEXT_DOWHAT), 'DOWHAT') + .setCheck(String); + this.setOutput(true, [Boolean, Number]); + this.setInputsInline(true); + } +} + +export const text_compare_to = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput("STR1") + .setCheck(String); + this.appendValueInput("STR2") + .appendField(Blockly.Msg.MIXLY_COMPARETO) + .setCheck(String); + this.setOutput(true, Number); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXLY_COMPARETO_HELP); + } +} + +export const text_capital = { + init: function () { + var TEXT_CAPITAL = [ + [Blockly.Msg.TEXT_UPPER, 'upper'], + [Blockly.Msg.TEXT_TITLE, 'title'], + [Blockly.Msg.TEXT_CAPITALIZE, 'capitalize'], + [Blockly.Msg.TEXT_SWAPCASE, 'swapcase'], + [Blockly.Msg.TEXT_LOWER, 'lower'] + ]; + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown(TEXT_CAPITAL), 'CAPITAL') + .setCheck(String); + this.setOutput(true, String); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('CAPITAL'); + var TOOLTIPS = { + 'upper': Blockly.Msg.MIXLY_MIXPY_TEXT_UPPER_TOOLTIP, + 'title': Blockly.Msg.MIXLY_MIXPY_TEXT_TITLE_TOOLTIP, + 'swapcase': Blockly.Msg.MIXLY_MIXPY_TEXT_SWAPCASE_TOOLTIP, + 'capitalize': Blockly.Msg.MIXLY_MIXPY_TEXT_CAPITALIZE_TOOLTIP, + 'lower': Blockly.Msg.MIXLY_MIXPY_TEXT_LOWER_TOOLTIP + }; + return TOOLTIPS[mode]; + }); + } +} + +export const text_center = { + init: function () { + var TEXT_CENTER = [ + [Blockly.Msg.TEXT_LJUST, 'ljust'], + [Blockly.Msg.TEXT_CENTER, 'center'], + [Blockly.Msg.TEXT_RJUST, 'rjust'] + ]; + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .appendField(new Blockly.FieldDropdown(TEXT_CENTER), 'CENTER') + .setCheck(String); + this.appendValueInput("WID") + .appendField(Blockly.Msg.MIXLY_WIDTH) + .setCheck(Number); + this.appendValueInput("Symbol") + .appendField(Blockly.Msg.MIXLY_RECT_Fill) + .setCheck(String); + this.setInputsInline(true); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TEXT_CENTER_TOOLTIP); + } +} + +export const text_find = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .setCheck(String); + this.appendValueInput("STR") + .appendField(Blockly.Msg.MIXLY_MID + Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_CHARACTER) + .setCheck(String); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_LIST_INDEX); + this.setInputsInline(true); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TEXT_FIND_TOOLTIP); + } +} + +export const text_join_seq = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_PYTHON_TEXT_JOIN_SEQ_USE_STR) + .setCheck(String); + this.appendValueInput('LIST') + .appendField(Blockly.Msg.MIXLY_PYTHON_TEXT_JOIN_SEQ_SEQ) + .setCheck('List', 'Tuple', 'Set', 'Dict'); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_TEXT_JOIN_SEQ_GET_STR); + this.setInputsInline(true); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TEXT_JOIN_SEQ_TOOLTIP); + } +} + +export const text_replace = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR") + .setCheck(String); + this.appendValueInput("STR1") + .appendField(Blockly.Msg.MIXLY_MIXPY_REPLACE) + .setCheck(String); + this.appendValueInput("STR2") + .appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_TO) + .setCheck(String); + this.setInputsInline(true); + this.setOutput(true, String); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TEXT_REPLACE_TOOLTIP); + } +} + +export const text_split = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput("VAR"); + this.appendValueInput("VAL") + .appendField(Blockly.Msg.LIST_SPLIT_AS); + this.appendDummyInput('') + .appendField(Blockly.Msg.LIST_SPLIT); + this.setOutput(true, "List"); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TEXT_SPLIT_TOOLTIP); + this.setInputsInline(true); + } +} + +export const text_strip = { + init: function () { + var STRIP = + [[Blockly.Msg.TEXT_TRIM_BOTH, 'strip'], [Blockly.Msg.TEXT_TRIM_LEFT, 'lstrip'], [Blockly.Msg.TEXT_TRIM_RIGHT, 'rstrip']]; + this.setColour(TEXTS_HUE); + this.appendValueInput('VAR') + this.appendDummyInput('') + .appendField(Blockly.Msg.TEXT_STRIM); + this.appendDummyInput('') + .appendField(new Blockly.FieldDropdown(STRIP), 'TOWHAT'); + this.appendDummyInput('') + .appendField(Blockly.Msg.TEXT_BLANK); + this.setOutput(true, String); + this.setInputsInline(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('TOWHAT'); + var TOOLTIPS = { + 'strip': Blockly.Msg.TEXT_TRIM_BOTH_TOOLTIP, + 'lstrip': Blockly.Msg.TEXT_TRIM_LEFT_TOOLTIP, + 'rstrip': Blockly.Msg.TEXT_TRIM_RIGHT_TOOLTIP + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const text_format = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(TEXTS_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_FORMAT) + //don't need to specify the data type in Python + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'Array'], [Blockly.Msg.LANG_MATH_STRING, 'Array'], [Blockly.Msg.LANG_MATH_BOOLEAN, 'Array']]), 'TYPE') + // .appendField(' ') + this.appendDummyInput("") + .appendField(new Blockly.FieldTextInput('str'), 'VAR'); + this.itemCount_ = 1; + this.updateShape_(); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setInputsInline(true); + this.setMutator(new Blockly.icons.MutatorIcon(['text_create_with_item'], this)); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TEXT_FORMAT_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('text_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('text_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.PROCEDURES_BEFORE_PARAMS); + } + } + } + }, + getVars: function () { + if (this.getFieldValue('VAR') != null) { + if ((this.getFieldValue('VAR').indexOf("'") == -1) && (this.getFieldValue('VAR').indexOf('"') == -1)) { + return [this.getFieldValue('VAR')]; + } + return []; + } + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + + } +}; + +export const text_create_with_container = { + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(TEXTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.TUPLE_CREATE_WITH_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const text_create_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(TEXTS_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_SET_VARIABLES_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.TUPLE_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const text_substring3 = text_substring +export const text_compareTo = text_compare_to +export const text_char_at3 = text_char_at + +export const text_format_noreturn = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(TEXTS_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROPYTHON_FORMAT) + //don't need to specify the data type in Python + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'Array'], [Blockly.Msg.LANG_MATH_STRING, 'Array'], [Blockly.Msg.LANG_MATH_BOOLEAN, 'Array']]), 'TYPE') + // .appendField(' ') + this.appendValueInput("VAR") + .setCheck(String); + this.itemCount_ = 1; + this.updateShape_(); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setInputsInline(true); + this.setMutator(new Blockly.icons.MutatorIcon(['text_create_with_item'], this)); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_TEXT_FORMAT_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('text_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('text_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.PROCEDURES_BEFORE_PARAMS); + } + } + } + } +}; + + + +export const text_encode = { + init: function () { + this.setColour(TEXTS_HUE); + var encode_decode = + [[Blockly.Msg.MIXPY_TEXT_ENCODE, 'encode'], [Blockly.Msg.MIXPY_TEXT_DECODE, 'decode']]; + var code = + [['ASCII', 'ASCII'], ['gb2312', 'gb2312'], ['gbk', 'gbk'], ['utf-8', 'utf-8'], ['utf-16', 'utf-16'], ['utf-32', 'utf-32']]; + this.appendDummyInput() + .appendField(new Blockly.FieldDropdown(code), 'CODE') + .appendField(' ') + this.appendValueInput("VAR") + .appendField(new Blockly.FieldDropdown(encode_decode), 'DIR') + .appendField(Blockly.Msg.LANG_MATH_STRING); + this.setOutput(true, String); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXPY_TEXT_ENCODE_DECODE_TOOLTIP); + + } +}; + + +export const text_eval = { + init: function () { + + this.setColour(TEXTS_HUE); + this.appendValueInput('VAR') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_PYTHON_TEXT_EVAL); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_TEXT_EVAL_RESULT); + this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TEXT_EVAL_TOOLTIP); + } +}; + +export const os_system = { + init: function () { + this.setColour(TEXTS_HUE); + this.appendValueInput('VAR') + .setCheck(String) + .appendField(Blockly.Msg.MIXLY_PYTHON_OS_SYSTEM); + this.setInputsInline(true); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_OS_SYSTEM_TOOLTIP); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/tuple.js b/mixly/boards/default_src/python/blocks/tuple.js new file mode 100644 index 00000000..8620f19c --- /dev/null +++ b/mixly/boards/default_src/python/blocks/tuple.js @@ -0,0 +1,772 @@ +import * as Blockly from 'blockly/core'; + +const TUPLE_HUE = 195; //'#5ec73d'//195; + +export const tuple_create_with = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(TUPLE_HUE); + this.appendDummyInput("") + //don't need to specify the data type in Python + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'Array'], [Blockly.Msg.LANG_MATH_STRING, 'Array'], [Blockly.Msg.LANG_MATH_BOOLEAN, 'Array']]), 'TYPE') + // .appendField(' ') + .appendField(new Blockly.FieldTextInput('mytup'), 'VAR'); + this.itemCount_ = 3; + this.updateShape_(); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['tuple_create_with_item'], this)); + this.setTooltip(Blockly.Msg.TUPLE_CREATE_WITH_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('tuple_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('tuple_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.TUPLE_CREATE_EMPTY_TITLE); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.TUPLE_CREATE_WITH_INPUT_WITH); + } + } + } + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const tuple_create_with_container = { + /** + * Mutator block for list container. + * @this Blockly.Block + */ + init: function () { + this.setColour(TUPLE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.TUPLE_CREATE_WITH_CONTAINER_TITLE_ADD); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.TUPLE_CREATE_WITH_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const tuple_create_with_item = { + /** + * Mutator bolck for adding items. + * @this Blockly.Block + */ + init: function () { + this.setColour(TUPLE_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.blockpy_SET_VARIABLES_NAME); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.TUPLE_CREATE_WITH_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const tuple_create_with_text2 = { + init: function () { + this.setColour(TUPLE_HUE); + this.appendDummyInput("") + //don't need to specify the data type in Python + // .appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'Array']]), 'TYPE') + // .appendField(' ') + // .appendField(Blockly.Msg.blockpy_MIXLY_TUPLE_CREATE) + .appendField(new Blockly.FieldTextInput('mytup'), 'VAR') + //.appendField(new Blockly.FieldTextInput('3',Blockly.FieldTextInput.math_number_validator), 'SIZE') + // .appendField(Blockly.Msg.MIXLY_MAKELISTFROM) + // .appendField(this.newQuote_(true)) + .appendField(' = (') + .appendField(new Blockly.FieldTextInput('0,0,0'), 'TEXT') + .appendField(')'); + // .appendField(this.newQuote_(false)) + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXPY_TOOLTIP_TUPLE_CREATE_WITH_TEXT); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } + // newQuote_: function(open) { + // if (open == this.RTL) { + // var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAqUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhggONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvBO3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5AoslLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg=='; + // } else { + // var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAn0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMfz9AylsaRRgGzvZAAAAAElFTkSuQmCC'; + // } + // return new Blockly.FieldImage(file, 12, 12, '"'); + // } +} + +export const tuple_create_with_text_return = { + init: function () { + this.setColour(TUPLE_HUE); + this.appendDummyInput("") + .appendField('(') + .appendField(new Blockly.FieldTextInput('0,0,0'), 'TEXT') + .appendField(')'); + // .appendField(this.newQuote_(false)) + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXPY_TOOLTIP_TUPLE_CREATE_WITH_TEXT); + // }, + // getVars: function() { + // return [this.getFieldValue('VAR')]; + // }, + // renameVar: function(oldName, newName) { + // if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + // this.setTitleValue(newName, 'VAR'); + // } + } + // newQuote_: function(open) { + // if (open == this.RTL) { + // var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAqUlEQVQI1z3KvUpCcRiA8ef9E4JNHhI0aFEacm1o0BsI0Slx8wa8gLauoDnoBhq7DcfWhggONDmJJgqCPA7neJ7p934EOOKOnM8Q7PDElo/4x4lFb2DmuUjcUzS3URnGib9qaPNbuXvBO3sGPHJDRG6fGVdMSeWDP2q99FQdFrz26Gu5Tq7dFMzUvbXy8KXeAj57cOklgA+u1B5AoslLtGIHQMaCVnwDnADZIFIrXsoXrgAAAABJRU5ErkJggg=='; + // } else { + // var file = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAKCAQAAAAqJXdxAAAAn0lEQVQI1z3OMa5BURSF4f/cQhAKjUQhuQmFNwGJEUi0RKN5rU7FHKhpjEH3TEMtkdBSCY1EIv8r7nFX9e29V7EBAOvu7RPjwmWGH/VuF8CyN9/OAdvqIXYLvtRaNjx9mMTDyo+NjAN1HNcl9ZQ5oQMM3dgDUqDo1l8DzvwmtZN7mnD+PkmLa+4mhrxVA9fRowBWmVBhFy5gYEjKMfz9AylsaRRgGzvZAAAAAElFTkSuQmCC'; + // } + // return new Blockly.FieldImage(file, 12, 12, '"'); + // } +} + +export const tuple_getIndex = { + init: function () { + this.setColour(TUPLE_HUE); + this.setOutput(true); + this.appendValueInput('TUP') + .setCheck('Tuple') + this.appendValueInput('AT') + .setCheck(Number) + + .appendField(Blockly.Msg.LANG_LISTS_GET_INDEX1); + this.appendDummyInput("") + .appendField(Blockly.Msg.LANG_LISTS_GET_INDEX2); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.TUPLE_GET_INDEX_TOOLTIP); + } +}; + +export const tuple_length = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(TUPLE_HUE); + this.appendValueInput('TUP'); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_LENGTH); + + this.setTooltip(Blockly.Msg.TUPLE_LENGTH_TOOLTIP); + this.setOutput(true, Number); + } +}; + +export const tuple_del = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(TUPLE_HUE); + this.appendValueInput('TUP') + .setCheck('Tuple') + this.appendDummyInput("") + .appendField(Blockly.Msg.TUPLE_DEL); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.TUPLE_DEL_TOOLTIP); + } +}; + +export const tuple_join = { + /** + * Block for list length. + * @this Blockly.Block + */ + init: function () { + this.setColour(TUPLE_HUE); + this.appendValueInput('TUP1') + .setCheck('Tuple') + this.appendDummyInput("") + .appendField(Blockly.Msg.TUPLE_JOIN) + this.appendValueInput('TUP2') + .setCheck('Tuple') + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.TUPLE_JOIN_TOOLTIP); + this.setOutput(true, "Tuple"); + } +}; + + +export const tuple_max = { + init: function () { + this.appendValueInput('TUP') + .setCheck('Tuple') + var max_min = + [[Blockly.Msg.blockpy_TUPLE_MAX, 'max'], [Blockly.Msg.blockpy_TUPLE_MIN, 'min'], [Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'sum']]; + this.setColour(TUPLE_HUE); + this.appendDummyInput("") + .appendField(Blockly.Msg.MIXLY_MICROBIT_JS_GET) + .appendField(new Blockly.FieldDropdown(max_min), 'DIR') + + + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('DIR'); + var TOOLTIPS = { + 'max': Blockly.Msg.MIXLY_TOOLTIP_TUPLE_MAX, + 'min': Blockly.Msg.MIXLY_TOOLTIP_TUPLE_MIN, + 'sum': Blockly.Msg.MIXLY_TOOLTIP_TUPLE_SUM + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const tuple_change_to = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, 'list'], + [Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, 'set'] + ]; + this.setColour(TUPLE_HUE); + this.appendValueInput('VAR') + .setCheck("Tuple") + // .appendField(Blockly.Msg.blockpy_USE_LIST); + this.appendDummyInput("") + .appendField(Blockly.Msg.A_TO_B) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'list': Blockly.Msg.TUPLE_TO_LISTS, + 'set': Blockly.Msg.TUPLE_TO_SET, + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const tuple_find = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MIXLY_LIST_INDEX, 'INDEX'], + [Blockly.Msg.MIXLY_LIST_COUNT, 'COUNT'] + ]; + this.setColour(TUPLE_HUE); + this.appendValueInput('VAR') + .setCheck('List') + this.appendValueInput('data') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(Blockly.Msg.HTML_VALUE) + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_DE) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + //.appendField(new Blockly.FieldTextInput('mylist'), 'VAR') + this.setInputsInline(true); + this.setOutput(true, Number); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'INDEX': Blockly.Msg.MIXLY_TOOLTIP_TUPLE_FIND_INDEX, + 'COUNT': Blockly.Msg.MIXLY_TOOLTIP_TUPLE_FIND_COUNT + + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const tuple_trig = { + init: function () { + var OPERATORS = [ + [Blockly.Msg.MIXLY_LIST_LEN, 'LEN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MAX, 'MAX'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MIN, 'MIN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE, 'AVERAGE'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN, 'MEDIAN'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_MODE, 'MODE'], + [Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV, 'STD_DEV'], + ]; + //this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL); + this.setColour(TUPLE_HUE); + this.setOutput(true, Number); + this.appendValueInput('data') + .setCheck('List') + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET) + .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP'); + this.setInputsInline(true); + // Assign 'this' to a variable for use in the tooltip closure below. + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('OP'); + var TOOLTIPS = { + 'LEN': Blockly.Msg.TUPLE_LENGTH_TOOLTIP, + 'SUM': Blockly.Msg.MATH_ONLIST_TOOLTIP_TUPLE_SUM, + 'MAX': Blockly.Msg.MATH_ONLIST_TOOLTIP_TUPLE_MAX, + 'MIN': Blockly.Msg.MATH_ONLIST_TOOLTIP_TUPLE_MIN, + 'AVERAGE': Blockly.Msg.MATH_ONLIST_TOOLTIP_TUPLE_AVERAGE, + 'MEDIAN': Blockly.Msg.MATH_ONLIST_TOOLTIP_TUPLE_MEDIAN, + 'MODE': Blockly.Msg.MATH_ONLIST_TOOLTIP_TUPLE_MODE, + 'STD_DEV': Blockly.Msg.MATH_ONLIST_TOOLTIP_TUPLE_STD_DEV + + }; + return TOOLTIPS[mode]; + }); + } +}; + +export const tuple_getSublist = { + /** + * Block for getting sublist. + * @this Blockly.Block + */ + init: function () { + this['WHERE_OPTIONS_1'] = [ + [Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST, 'FIRST'] + ]; + this['WHERE_OPTIONS_2'] = [ + [Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START, 'FROM_START'], + [Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END, 'FROM_END'], + [Blockly.Msg.LISTS_GET_SUBLIST_END_LAST, 'LAST'] + ]; + this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL); + this.setColour(TUPLE_HUE); + this.appendValueInput('LIST') + .setCheck('List') + //.appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL) + // if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) { + // this.appendDummyInput('TAIL') + // .appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL); + // } + this.appendDummyInput('') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET); + this.appendDummyInput('AT1'); + this.appendDummyInput('AT2'); + this.setInputsInline(true); + this.setOutput(true, 'List'); + this.updateAt_(1, true); + this.updateAt_(2, true); + this.setTooltip(Blockly.Msg.PYTHON_TUPLE_GET_SUBLIST_TOOLTIP); + }, + /** + * Create XML to represent whether there are 'AT' inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + var isAt1 = this.getInput('AT1').type == Blockly.INPUT_VALUE; + container.setAttribute('at1', isAt1); + var isAt2 = this.getInput('AT2').type == Blockly.INPUT_VALUE; + container.setAttribute('at2', isAt2); + return container; + }, + /** + * Parse XML to restore the 'AT' inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var isAt1 = (xmlElement.getAttribute('at1') == 'true'); + var isAt2 = (xmlElement.getAttribute('at2') == 'true'); + this.updateAt_(1, isAt1); + this.updateAt_(2, isAt2); + }, + /** + * Create or delete an input for a numeric index. + * This block has two such inputs, independant of each other. + * @param {number} n Specify first or second input (1 or 2). + * @param {boolean} isAt True if the input should exist. + * @private + * @this Blockly.Block + */ + updateAt_: function (n, isAt) { + // Create or delete an input for the numeric index. + // Destroy old 'AT' and 'ORDINAL' inputs. + this.removeInput('AT' + n); + this.removeInput('ORDINAL' + n, true); + // Create either a value 'AT' input or a dummy input. + if (isAt) { + this.appendValueInput('AT' + n).setCheck(Number); + if (Blockly.Msg.TEXT_CHARAT_TAIL) { + this.appendDummyInput('ORDINAL' + n) + .appendField(Blockly.Msg.TEXT_CHARAT_TAIL); + } + } else { + this.appendDummyInput('AT' + n); + } + var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n], + function (value) { + var newAt = (value == 'FROM_START') || (value == 'FROM_END'); + // The 'isAt' variable is available due to this function being a + // closure. + if (newAt != isAt) { + var block = this.sourceBlock_; + block.updateAt_(n, newAt); + // This menu has been destroyed and replaced. + // Update the replacement. + block.setFieldValue(value, 'WHERE' + n); + return null; + } + return undefined; + }); + this.getInput('AT' + n) + .appendField(menu, 'WHERE' + n); + if (n == 1) { + this.moveInputBefore('AT1', 'AT2'); + if (this.getInput('ORDINAL1')) { + this.moveInputBefore('ORDINAL1', 'AT2'); + } + } + // if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) { + // this.moveInputBefore('TAIL', null); + // } + } +}; + +export const tuple_create_with_noreturn = { + /** + * Block for creating a list with any number of elements of any type. + * @this Blockly.Block + */ + init: function () { + this.setColour(TUPLE_HUE); + this.itemCount_ = 3; + this.updateShape_(); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, "Tuple") + this.setMutator(new Blockly.icons.MutatorIcon(['tuple_create_with_item'], this)); + this.setTooltip(Blockly.Msg.TUPLE_CREATE_WITH_TOOLTIP); + }, + /** + * Create XML to represent list inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('tuple_create_with_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('tuple_create_with_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.TUPLE_CREATE_EMPTY_TITLE); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.TUPLE_CREATE_WITH_INPUT_WITH); + } + } + } + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setTitleValue(newName, 'VAR'); + } + } +}; + +export const tuple_get_sublist = { + /** + * Block for getting sublist. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL); + this.setColour(TUPLE_HUE); + this.appendValueInput('LIST') + this.appendDummyInput('') + this.appendValueInput('AT1') + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + " " + Blockly.Msg.LISTS_GET_INDEX_FROM_START); + this.appendValueInput('AT2') + .appendField(Blockly.Msg.TEXT_CHARAT_TAIL + " " + Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START); + this.appendDummyInput() + .appendField(Blockly.Msg.TEXT_CHARAT_TAIL); + this.setInputsInline(true); + this.setOutput(true, 'Tuple'); + this.setTooltip(Blockly.Msg.PYTHON_TUPLE_GET_SUBLIST_TOOLTIP); + } +} + +export const tuple_get_random_item = { + init: function () { + this.setColour(TUPLE_HUE); + this.appendValueInput("TUP"); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_STORAGE_GET + " " + Blockly.Msg.LISTS_GET_INDEX_RANDOM) + this.setTooltip(Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM); + this.setOutput(true); + } +}; + +export const tuple_totuple = { + init: function () { + this.setColour(TUPLE_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_TOTUPLE); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_TOOLTIP_TOTUPLE); + } +}; +function getCurrentTimeTuple() { + var now = new Date(); + var year = now.getFullYear(); + var month = now.getMonth() + 1; // 月份从 0 开始,所以要加 1 + var day = now.getDate(); + var hour = now.getHours(); + var minute = now.getMinutes(); + var second = now.getSeconds(); + + // 返回元组格式的时间字符串 + return year + "," + month + "," + day + "," + hour + "," + minute + "," + second ; +} +export const tuple_input = { + init: function () { + this.setColour(TUPLE_HUE); + this.appendDummyInput("") + .appendField('(') + .appendField(new Blockly.FieldTextInput(getCurrentTimeTuple()),"CONTENT") + .appendField(')'); + this.setOutput(true); + } +}; + + +export const tuple_create_llm_params= { + init: function () { + this.setColour(TUPLE_HUE); + this.appendValueInput("params") + .appendField('(') + .appendField(Blockly.Msg.MIXLY_NAME_OF_PARAMS) + this.appendDummyInput() + .appendField(',') + .appendField(Blockly.Msg.MIXLY_TYPE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_TYPE_BOOLEAN,"boolean"], + [Blockly.Msg.MIXLY_TYPE_STRING,"string"], + [Blockly.Msg.MIXLY_TYPE_NUMBER,"number"], + [Blockly.Msg.MIXLY_TYPE_INTEGER,"integer"], + [Blockly.Msg.MIXLY_TYPE_NULL,"null"] + ]),"type") + this.appendValueInput("des") + .appendField(',') + .appendField(Blockly.Msg.MIXLY_DESCRIPTION) + this.appendDummyInput() + .appendField(')'); + this.setOutput(true); + this.setInputsInline(true); + this.setTooltip(Blockly.Msg.MIXPY_TOOLTIP_TUPLE_CREATE_WITH_TEXT); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/blocks/utility.js b/mixly/boards/default_src/python/blocks/utility.js new file mode 100644 index 00000000..9a211e1e --- /dev/null +++ b/mixly/boards/default_src/python/blocks/utility.js @@ -0,0 +1,445 @@ +/** + * @license + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Utility blocks for Blockly. + * @author acbart@vt.edu (Austin Cory Bart) + */ +import * as Blockly from 'blockly/core'; + +const UTILITY_HUE = 160; + +export const raw_table = { + // Container. + init: function () { + this.setColour(UTILITY_HUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendDummyInput() + .appendField('Tabular Abstraction:'); + this.appendDummyInput() + .appendField(new Blockly.FieldTable(''), 'TEXT'); + } +}; + +export const raw_block = { + // Container. + init: function () { + this.setColour(UTILITY_HUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendDummyInput() + .appendField('Code Block:'); + this.appendDummyInput() + .appendField(new Blockly.FieldMultilineInput(''), 'TEXT'); + } +}; + +export const raw_expression = { + // Container. + init: function () { + this.setColour(UTILITY_HUE); + this.appendDummyInput() + .appendField('Code Expression:'); + this.appendDummyInput() + .appendField(new Blockly.FieldMultilineInput(''), 'TEXT'); + this.setOutput(true); + } +}; + +export const raw_empty = { + // Container. + init: function () { + this.setColour(UTILITY_HUE); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.appendValueInput('VALUE') + .appendField(''); + this.setInputsInline(false); + } +}; + +export const text_comment = { + // Text value. + init: function () { + this.setColour(UTILITY_HUE); + this.appendDummyInput() + .appendTitle('Comment:') + .appendTitle(new Blockly.FieldTextInput(''), 'TEXT'); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip('This comment will be ignored by Python'); + } +}; + +export const type_check = { + // Set element at index. + init: function () { + this.setColour(UTILITY_HUE); + this.appendValueInput('VALUE') + .appendField(Blockly.Msg.TYPE_CHECK); + this.setInputsInline(false); + this.setOutput(true, 'Type'); + //this.setPreviousStatement(true); + //this.setNextStatement(true); + } +}; + + +export const text_print_multiple = { + /** + * Block for printing multiple things (including nothing) + * @this Blockly.Block + */ + init: function () { + this.setColour(UTILITY_HUE); + this.itemCount_ = 1; + this.updateShape_(); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setMutator(new Blockly.icons.MutatorIcon(['text_print_multiple_item'], this)); + this.setTooltip(Blockly.Msg.TEXT_PRINT_TOOLTIP); + }, + /** + * Create XML to represent print inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = Blockly.Block.obtain(workspace, + 'text_print_multiple_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var x = 0; x < this.itemCount_; x++) { + var itemBlock = workspace.newBlock('text_print_multiple_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('PRINT' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + // Store a pointer to any connected child blocks. + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var x = 0; + while (itemBlock) { + var input = this.getInput('PRINT' + x); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + x++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('PRINT' + i)) { + this.removeInput('PRINT' + i); + i++; + } + } + + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField("print"); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('PRINT' + i); + if (i == 0) { + input.appendField("print"); + } + } + } + } +}; + +export const text_print_multiple_container = { + // Container. + init: function () { + this.setColour(UTILITY_HUE); + this.appendDummyInput() + .appendField('print'); + this.appendStatementInput('STACK'); + this.setTooltip(''); + this.contextMenu = false; + } +}; +export const text_print_multiple_item = { + // Add items. + init: function () { + this.setColour(UTILITY_HUE); + this.appendDummyInput() + .appendField('item'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + this.contextMenu = false; + } +}; + +export const function_call = { + /** + * Block for printing multiple things (including nothing) + * @this Blockly.Block + */ + init: function () { + this.setColour(UTILITY_HUE); + this.itemCount_ = 1; + this.hasReturn_ = false; + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput("str"), 'NAME'); + this.updateShape_(); + this.setMutator(new Blockly.icons.MutatorIcon(['function_call_item'], this)); + this.setTooltip("Can be used to call any function"); + }, + /** + * Create XML to represent print inputs. + * @return {Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + container.setAttribute('hasReturn', this.hasReturn_ ? "TRUE" : "FALSE"); + return container; + }, + /** + * Parse XML to restore the list inputs. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.hasReturn_ = xmlElement.getAttribute('hasReturn') === "TRUE"; + this.updateShape_(); + }, + /** + * Populate the mutator's dialog with this block's components. + * @param {!Blockly.Workspace} workspace Mutator's workspace. + * @return {!Blockly.Block} Root block in mutator. + * @this Blockly.Block + */ + decompose: function (workspace) { + var containerBlock = Blockly.Block.obtain(workspace, + 'function_call_container'); + containerBlock.initSvg(); + + containerBlock.setFieldValue(this.hasStatements_ ? 'TRUE' : 'FALSE', + 'RETURN'); + + var connection = containerBlock.getInput('STACK').connection; + for (var x = 0; x < this.itemCount_; x++) { + var itemBlock = workspace.newBlock('function_call_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + /** + * Notification that the procedure's return state has changed. + * @param {boolean} returnState New return state + * @this Blockly.Block + */ + setReturn: function (returnState) { + this.unplug(true, true); + this.setOutput(returnState); + this.setPreviousStatement(!returnState); + this.setNextStatement(!returnState); + if (this.rendered) { + this.render(); + } + }, + /** + * Reconfigure this block based on the mutator dialog's components. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + + this.hasReturn_ = containerBlock.getFieldValue("RETURN") === "TRUE"; + + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ARGUMENT' + i).connection.connect(connections[i]); + } + } + }, + /** + * Store pointers to any connected child blocks. + * @param {!Blockly.Block} containerBlock Root block in mutator. + * @this Blockly.Block + */ + saveConnections: function (containerBlock) { + // Store a pointer to any connected child blocks. + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var x = 0; + while (itemBlock) { + var input = this.getInput('ARGUMENT' + x); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + x++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + /** + * Modify this block to have the correct number of inputs. + * @private + * @this Blockly.Block + */ + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ARGUMENT' + i)) { + this.removeInput('ARGUMENT' + i); + i++; + } + } + + // Rebuild block. + for (var i = 0; i < this.itemCount_; i++) { + this.appendValueInput('ARGUMENT' + i); + } + + // Set whether returns anything + this.setReturn(this.hasReturn_); + } +}; + +export const function_call_container = { + // Container. + init: function () { + this.setColour(UTILITY_HUE); + this.appendDummyInput() + .appendField('Arguments'); + this.appendStatementInput('STACK'); + this.appendDummyInput() + .setAlign(Blockly.inputs.Align.RIGHT) + .appendField('has return') + .appendField(new Blockly.FieldCheckbox('TRUE'), + 'RETURN'); + this.setTooltip(''); + this.contextMenu = false; + } +}; +export const function_call_item = { + // Add items. + init: function () { + this.setColour(UTILITY_HUE); + this.appendDummyInput() + .appendField('argument'); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(''); + this.contextMenu = false; + } +}; + +export const attribute_access = { + init: function () { + this.appendValueInput("MODULE") + .setCheck(null); + this.appendValueInput("NAME") + .setCheck(null) + .appendField("."); + this.setInputsInline(true); + this.setOutput(true, null); + this.setColour(230); + this.setTooltip(''); + this.setHelpUrl(''); + } +}; diff --git a/mixly/boards/default_src/python/blocks/variables.js b/mixly/boards/default_src/python/blocks/variables.js new file mode 100644 index 00000000..edc892ef --- /dev/null +++ b/mixly/boards/default_src/python/blocks/variables.js @@ -0,0 +1,331 @@ +import * as Blockly from 'blockly/core'; +import Names from '../others/names'; + +const VARIABLES_HUE = 330//'#af5180'//330; + +// ************************************************************************ +// THIS SECTION IS INSERTED INTO BLOCKLY BY BLOCKLYDUINO. +// export const variables_declare = { +// // Variable setter. +// init: function() { +// this.setColour(VARIABLES_HUE); +// this.appendValueInput('VALUE', null) +// .appendField(Blockly.Msg.MIXLY_DECLARE) +// .appendField(new Blockly.FieldTextInput(''), 'VAR') +// //.appendField(Blockly.Msg.MIXLY_AS) +// //.appendField(new Blockly.FieldDropdown([[Blockly.Msg.MIXLY_NUMBER, 'number'], [Blockly.Msg.LANG_MATH_STRING, 'string'], [Blockly.Msg.LANG_MATH_BOOLEAN, 'boolean']]), 'TYPE') +// .appendField(Blockly.Msg.MIXLY_VALUE); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// this.setTooltip(Blockly.Msg.MIXLY_TOOLTIP_VARIABLES_DECLARE); +// }, +// getVars: function() { +// return [this.getFieldValue('VAR')]; +// }, +// renameVar: function(oldName, newName) { +// if (Names.equals(oldName, this.getFieldValue('VAR'))) { +// this.setTitleValue(newName, 'VAR'); +// } +// } +// }; +// ************************************************************************ + +export const variables_get = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendDummyInput() + .appendField(new Blockly.FieldTextInput(''), 'VAR') + this.setOutput(true); + this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP); + }, + getVars: function () { + return [this.getFieldValue('VAR')]; + }, + renameVar: function (oldName, newName) { + if (Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + }/*, + onchange: function() { + var varName = Blockly.Arduino.variableDB_.getName(this.getFieldValue('VAR'),Blockly.Variables.NAME_TYPE); + if(Blockly.Arduino.definitions_['var_declare'+varName]){ + this.setWarningText(null); + }else{ + this.setWarningText(Blockly.Msg.MIXLY_WARNING_NOT_DECLARE); + } + }*/ +}; + +// export const variables_set = { +// init: function() { +// this.setColour(VARIABLES_HUE); +// this.appendValueInput('VALUE') +// .appendField(new Blockly.FieldTextInput(''), 'VAR') +// .appendField(Blockly.Msg.MIXLY_VALUE2); +// this.setPreviousStatement(true); +// this.setNextStatement(true); +// this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP); +// }, +// getVars: function() { +// return [this.getFieldValue('VAR')]; +// }, +// renameVar: function(oldName, newName) { +// if (Names.equals(oldName, this.getFieldValue('VAR'))) { +// this.setFieldValue(newName, 'VAR'); +// } +// }/*, +// onchange: function() { +// var varName = Blockly.Arduino.variableDB_.getName(this.getFieldValue('VAR'),Blockly.Variables.NAME_TYPE); +// if(Blockly.Arduino.definitions_['var_declare'+varName]){ +// this.setWarningText(null); +// }else{ +// this.setWarningText(Blockly.Msg.MIXLY_WARNING_NOT_DECLARE); +// } +// }*/ +// }; +export const variables_set = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendValueInput('VALUE') + .appendField(new Blockly.FieldTextInput(''), 'VAR') + .appendField(Blockly.Msg.MIXLY_VALUE2); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP); + }, + getVars: function () { + var varValue = this.getFieldValue('VAR'); + if (varValue == null) { + return []; + } + return varValue.split(","); + }, + renameVar: function (oldName, newName) { + if (Names.equals(oldName, this.getFieldValue('VAR'))) { + this.setFieldValue(newName, 'VAR'); + } + } +}; +/** + * Block for basic data type change. + * @this Blockly.Block + */ +export const variables_change = { + init: function () { + this.setColour(VARIABLES_HUE); + var DATATYPES = + [ + [Blockly.Msg.LANG_MATH_INT, "int"], + [Blockly.Msg.LANG_MATH_FLOAT, "float"], + [Blockly.Msg.LANG_MATH_BOOLEAN, "bool"], + // [Blockly.Msg.MIXLY_MICROPYTHON_TYPE_COMPLEX, "complex"], + [Blockly.Msg.LANG_MATH_STRING, "str"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, "list"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, "tuple"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, "dict"], + [Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, "set"], + [Blockly.Msg.LANG_MATH_BYTE, "bytes"] + ]; + this.appendValueInput('MYVALUE') + .appendField(new Blockly.FieldDropdown(DATATYPES), 'OP'); + // Assign 'this' to a variable for use in the tooltip closure below. + this.setOutput(true); + // this.setInputsInline(true); + + } +}; + + +export const variables_global = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendValueInput("VAR") + .appendField(Blockly.Msg.MIXLY_PYTHON_GLOBAL) + .setCheck("var"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.TEXT_PRINT_TOOLTIP); + } +}; + + +export const controls_type = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendValueInput("DATA") + .appendField(Blockly.Msg.MICROBIT_PYTHON_TYPE); + // this.setInputsInline(true); + this.setOutput(true); + this.setTooltip(Blockly.Msg.MICROBIT_PYTHON_TYPE); + } +}; + + +export const controls_typeLists = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_MICROBIT_PY_CONTORL_GET_TYPE) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.LANG_MATH_INT, "int"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_FLOAT, "float"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING, "str"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, "list"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, "tuple"], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, "dict"], + [Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, "set"], + [Blockly.Msg.LANG_MATH_BYTE, "bytes"], + // [Blockly.Msg.MIXLY_MICROBIT_IMAGE,"image"], + [Blockly.Msg.LOGIC_NULL, "type(None)"]]), "type"); + //整数、浮点数、字符串、列表、元组、字典、集合、图像不太对, unfinished + this.setInputsInline(true); + this.setOutput(true); + var thisBlock = this; + this.setTooltip(function () { + var mode = thisBlock.getFieldValue('type'); + var mode0 = Blockly.Msg.MICROBIT_controls_TypeLists; + var TOOLTIPS = { + 'int': Blockly.Msg.LANG_MATH_INT, + 'float': Blockly.Msg.MIXLY_MICROBIT_TYPE_FLOAT, + 'str': Blockly.Msg.MIXLY_MICROBIT_TYPE_STRING, + 'list': Blockly.Msg.MIXLY_MICROBIT_TYPE_LIST, + 'tuple': Blockly.Msg.MIXLY_MICROBIT_TYPE_TUPLE, + 'dict': Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, + 'set': Blockly.Msg.blockpy_SET_CREATE_WITH_CONTAINER_TITLE_ADD, + 'image': Blockly.Msg.MIXLY_MICROBIT_IMAGE, + 'bytes': Blockly.Msg.LANG_MATH_BYTE, + 'NoneType': Blockly.Msg.LOGIC_NULL + }; + return mode0 + TOOLTIPS[mode]; + }); + } +}; + +export const lists_zip = { + init: function () { + this.setColour(VARIABLES_HUE); + + this.itemCount_ = 2; + this.updateShape_(); + this.setInputsInline(true); + this.setPreviousStatement(false); + this.setNextStatement(false); + this.setOutput(true, "List") + this.setMutator(new Blockly.icons.MutatorIcon(['lists_zip_item'], this)); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_LISTS_ZIP_TOOLTIP); + }, + mutationToDom: function () { + var container = document.createElement('mutation'); + container.setAttribute('items', this.itemCount_); + return container; + }, + domToMutation: function (xmlElement) { + this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); + this.updateShape_(); + }, + decompose: function (workspace) { + var containerBlock = + workspace.newBlock('lists_zip_container'); + containerBlock.initSvg(); + var connection = containerBlock.getInput('STACK').connection; + for (var i = 0; i < this.itemCount_; i++) { + var itemBlock = workspace.newBlock('lists_zip_item'); + itemBlock.initSvg(); + connection.connect(itemBlock.previousConnection); + connection = itemBlock.nextConnection; + } + return containerBlock; + }, + compose: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + // Count number of inputs. + var connections = []; + var i = 0; + while (itemBlock) { + connections[i] = itemBlock.valueConnection_; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + i++; + } + this.itemCount_ = i; + this.updateShape_(); + // Reconnect any child blocks. + for (var i = 0; i < this.itemCount_; i++) { + if (connections[i]) { + this.getInput('ADD' + i).connection.connect(connections[i]); + } + } + }, + saveConnections: function (containerBlock) { + var itemBlock = containerBlock.getInputTargetBlock('STACK'); + var i = 0; + while (itemBlock) { + var input = this.getInput('ADD' + i); + itemBlock.valueConnection_ = input && input.connection.targetConnection; + i++; + itemBlock = itemBlock.nextConnection && + itemBlock.nextConnection.targetBlock(); + } + }, + updateShape_: function () { + // Delete everything. + if (this.getInput('EMPTY')) { + this.removeInput('EMPTY'); + } else { + var i = 0; + while (this.getInput('ADD' + i)) { + this.removeInput('ADD' + i); + i++; + } + } + // Rebuild block. + if (this.itemCount_ == 0) { + this.appendDummyInput('EMPTY') + .appendField(Blockly.Msg.MIXLY_PYTHON_LISTS_ZIP); + } else { + for (var i = 0; i < this.itemCount_; i++) { + var input = this.appendValueInput('ADD' + i); + if (i == 0) { + input.appendField(Blockly.Msg.MIXLY_PYTHON_LISTS_ZIP); + } + } + } + } +}; + +export const lists_zip_container = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_LISTS_ZIP); + this.appendStatementInput('STACK'); + this.setTooltip(Blockly.Msg.MIXLY_MIXPY_INOUT_PRINT_MANY_CONTAINER_TOOLTIP); + this.contextMenu = false; + } +}; + +export const lists_zip_item = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendDummyInput() + .appendField(Blockly.Msg.MIXLY_PYTHON_LISTS_ZIP_ITEM); + this.setPreviousStatement(true); + this.setNextStatement(true); + this.setTooltip(Blockly.Msg.MIXLY_PYTHON_LISTS_ZIP_ITEM_TOOLTIP); + this.contextMenu = false; + } +}; + +export const unpack_iterable_object = { + init: function () { + this.setColour(VARIABLES_HUE); + this.appendValueInput('VAR') + .appendField(Blockly.Msg.MIXLY_VARIABLE_UNPACK) + .appendField(new Blockly.FieldDropdown([ + [Blockly.Msg.MIXLY_PYTHON_LISTS_ZIP_ITEM, '*'], + [Blockly.Msg.MIXLY_MICROBIT_TYPE_DICT, '**'] + ]), 'TYPE'); + this.setTooltip(''); + this.setOutput(true); + } +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/converters/control.js b/mixly/boards/default_src/python/converters/control.js new file mode 100644 index 00000000..1f9b29e6 --- /dev/null +++ b/mixly/boards/default_src/python/converters/control.js @@ -0,0 +1,98 @@ +'use strict'; + +pbc.globalFunctionD['type'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + return block("controls_type", func.lineno, {}, { + 'DATA': py2block.convert(args[0]), + }, { + "inline": "false" + }); +} + + +function typeName() { + function converter(py2block, node, id, ctx, nodeName) { + return block("controls_typeLists", node.lineno, {'type': nodeName}, {}, { + "inline": "true" + }); + } + + return converter; +} + +pbc.reservedNameD['int'] = typeName(); +pbc.reservedNameD['float'] = typeName(); +pbc.reservedNameD['str'] = typeName(); +pbc.reservedNameD['list'] = typeName(); +pbc.reservedNameD['tuple'] = typeName(); +pbc.reservedNameD['dict'] = typeName(); +pbc.reservedNameD['set'] = typeName(); +pbc.reservedNameD['NoneType'] = typeName(); + +pbc.globalFunctionD['range'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + var args_len = args.length; + if (args_len > 3 || args_len < 1) { + throw new Error("Incorrect number of arguments"); + } + var arg1block, arg2block, arg3block; + if (args_len == 1) { + arg2block = py2block.convert(args[0]); + var args0 = { + _astname: "Num", + n: { + 'v': 0 + } + + }; + arg1block = py2block.convert(args0); + var args2 = { + _astname: "Num", + n: { + 'v': 1 + } + }; + arg3block = py2block.convert(args2); + }else if (args_len == 2) { + var args2 = { + _astname: "Num", + n: { + 'v': 1 + } + }; + arg1block = py2block.convert(args[0]); + arg2block = py2block.convert(args[1]); + arg3block = py2block.convert(args2); + }else { + arg1block = py2block.convert(args[0]); + arg2block = py2block.convert(args[1]); + arg3block = py2block.convert(args[2]); + } + + return block("controls_range", func.lineno, { + }, { + 'FROM': arg1block, + 'TO': arg2block, + 'STEP': arg3block + }, { + "inline": "true" + }); +}; + +pbc.moduleFunctionD.get('_thread')['start_new_thread'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + pbc.pinType = "pins_callback"; + var callback = py2block.convert(args[0]); + pbc.pinType=null; + var tupblock = py2block.convert(args[1]); + return [block("controls_thread", func.lineno, {},{ + "callback":callback, + "VAR":tupblock + },{ + "inline": "true" + })]; +}; +//for i in ...在python_to_blockly.js中实现 diff --git a/mixly/boards/default_src/python/converters/dicts.js b/mixly/boards/default_src/python/converters/dicts.js new file mode 100644 index 00000000..741aa23f --- /dev/null +++ b/mixly/boards/default_src/python/converters/dicts.js @@ -0,0 +1,153 @@ +'use strict'; + +pbc.assignD.get('Dict')['check_assign'] = function (py2block, node, targets, value) { + if (value._astname === "Dict") + return true; + return false; +} + +pbc.assignD.get('Dict')['create_block'] = function (py2block, node, targets, value) { + var keys = value.keys; + var values = value.values; + + var keyList = []; + var valueList = []; + for (var i = 0; i < keys.length; i+= 1) { + var sourceCode = py2block.getSourceCode(node).split('\n')[keys[i].lineno - 1]; + var s = keys[i].col_offset; + var e = sourceCode.indexOf(":", keys[i].col_offset); + keyList["KEY"+i] = sourceCode.substring(s, e).trim(); + valueList["ADD"+i] = py2block.convert(values[i]); + } + keyList['VAR'] = py2block.Name_str(targets[0]); + + return block("dicts_create_with", node.lineno, keyList, valueList, { + "inline": "false" + }, { + "@items": keys.length + }); +} + +pbc.objectFunctionD.get('keys')['Dict'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("dicts_keys", func.lineno, {}, { + "DICT": objblock, + }, { + "inline": "true" + }); +}; + +pbc.objectFunctionD.get('get')['Dict'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1 && args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + if (args.length == 2){ + var args0 = py2block.convert(args[0]); + var args1 = py2block.convert(args[1]); + return block("dicts_get_default", func.lineno, {}, { + "DICT": objblock, + "KEY": args0, + "VAR": args1, + }, { + "inline": "true" + }); + } + else{ + + var args1block = { + _astname: "Name", + id: { + 'v': 'None' + } + }; + var args0 = py2block.convert(args[0]); + var args1 = py2block.convert(args1block); + return block("dicts_get_default", func.lineno, {}, { + "DICT": objblock, + "KEY": args0, + "VAR": args1, + }, { + "inline": "true" + }); + } +}; + +//d['key']在python_to_blockly.js中实现 + +//d['key'] = 11;在python_to_blockly.js中实现 + +//del d['key'];在python_to_blockly.js中实现 + +//d.clear()在lists.js中实现 + +//d.pop('key')在set.js中实现 + + +pbc.objectFunctionD.get('setdefault')['Dict'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var args0 = py2block.convert(args[0]); + var args1 = py2block.convert(args[1]); + return [block("dicts_setdefault", func.lineno, {}, { + "DICT": objblock, + "KEY": args0, + "VAR": args1, + }, { + "inline": "true" + })]; +}; + + +pbc.objectFunctionD.get('items')['Dict'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("dicts_items", func.lineno, {}, { + "DICT": objblock, + }, { + "inline": "true" + }); +}; + + +pbc.objectFunctionD.get('values')['Dict'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("dicts_values", func.lineno, {}, { + "DICT": objblock, + }, { + "inline": "true" + }); +}; + + +pbc.globalFunctionD['dict'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length > 1) { + throw new Error("Incorrect number of arguments"); + } + if (args.length ==0){ + return block("dicts_create_with_noreturn", node.lineno, {},{} + , { + "inline": "true", + }, { + "@items": 0 + }); + } + if (args.length ==1){ + var numblock = py2block.convert(args[0]); + return block("dicts_todict", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); + } +} diff --git a/mixly/boards/default_src/python/converters/lists.js b/mixly/boards/default_src/python/converters/lists.js new file mode 100644 index 00000000..e86f4ac6 --- /dev/null +++ b/mixly/boards/default_src/python/converters/lists.js @@ -0,0 +1,243 @@ +'use strict'; + +pbc.assignD.get('List')['check_assign'] = function (py2block, node, targets, value) { + if (value._astname === "List") + return true; + return false; +} + +pbc.assignD.get('List')['create_block'] = function (py2block, node, targets, value) { + return block("lists_create_with", node.lineno, { + 'VAR': py2block.Name_str(targets[0]) + }, + py2block.convertElements("ADD", value.elts), { + "inline": elts.length < 4 ? "false" : "true", + }, { + "@items": value.elts.length + }); +} + + +//mylist[0]在python_to_blockly.js中实现 +//mylist[0:2]在python_to_blockly.js中实现 + + +function listTrig(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return block("list_trig", func.lineno, { + 'OP':mode + }, { + "data": argblock, + }, { + "inline": "true" + }); + }; + return converter; +} + +pbc.globalFunctionD['sum'] = listTrig('SUM'); +pbc.globalFunctionD['math_mean'] = listTrig('AVERAGE'); +pbc.globalFunctionD['math_median'] = listTrig('MEDIAN'); +pbc.globalFunctionD['math_modes'] = listTrig('MODE'); +pbc.globalFunctionD['math_standard_deviation'] = listTrig('STD_DEV'); + + +//mylist[0] = 0在python_to_blockly.js中实现 + + +pbc.objectFunctionD.get('insert')['List'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var atblock = py2block.convert(args[0]); + var valblock = py2block.convert(args[1]); + return [block("lists_insert_value", func.lineno, {}, { + "LIST": objblock, + "AT": atblock, + "VALUE": valblock, + }, { + "inline": "true" + })]; +}; + +function listAppendExtend(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return [block("lists_append_extend", func.lineno, { + "OP":mode + }, { + "LIST": objblock, + "DATA": argblock + }, { + "inline": "true" + })]; + }; + return converter; +} +pbc.objectFunctionD.get('append')['List'] = listAppendExtend('append'); +pbc.objectFunctionD.get('extend')['List'] = listAppendExtend('extend'); + + +//del mylist[0]在python_to_blockly.js中实现 + +pbc.objectFunctionD.get('remove')['List'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return [block("lists_remove_at", func.lineno, { + "OP":"remove" + }, { + "LIST": objblock, + "DATA": argblock + }, { + "inline": "true" + })]; +}; + + +//mylist.pop(0)在set.js中实现 +//random.choice(mylist)在text.js中实现 + +function listFindCount(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("lists_find", func.lineno, { + 'OP':mode + }, { + "VAR": objblock, + "data": argblock + }, { + "inline": "true" + }); + }; + return converter; +} +pbc.objectFunctionD.get('index')['List'] = listFindCount('INDEX'); +pbc.objectFunctionD.get('count')['List'] = listFindCount('COUNT'); + + +pbc.globalFunctionD['lists_sort'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 3 && args[1]._astname === "Str" + && args[2]._astname === "Name") { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + var type = py2block.Str_value(args[1]); + var reverse = py2block.Name_str(args[2]); + if(reverse == "True"){ + reverse = '-1'; + }else if(reverse == "False"){ + reverse = '1'; + }else{ + throw new Error("not implement"); + } + return block("lists_sort", func.lineno, { + 'TYPE': type, + 'DIRECTION':reverse + }, { + 'LIST': argblock + }, { + "inline": "true" + }); +} + + +pbc.objectFunctionD.get('reverse')['List'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("lists_reverse", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + })]; +}; + + +pbc.objectFunctionD.get('clear')['List'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return [block("lists_clear", func.lineno, {}, { + "VAR": objblock, + }, { + "inline": "true" + })]; +}; + +pbc.globalFunctionD['list'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length > 1) { + throw new Error("Incorrect number of arguments"); + } + if (args.length ==0){ + return block("lists_create_with_noreturn", node.lineno, {},{} + , { + "inline": "true", + }, { + "@items": 0 + }); + } + if (args.length ==1){ + var numblock = py2block.convert(args[0]); + return block("list_tolist", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }) + } +} + +pbc.globalFunctionD['zip'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + + var d = py2block.convertElements("ADD", args); + + return block("lists_zip", node.lineno, { + }, d, { + "inline": "true", + }, { + "@items":args.length + }); + } + +pbc.moduleFunctionD.get('random')['sample'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var listname = py2block.convert(args[0]); + var varblock = py2block.convert(args[1]); + return block("lists_get_random_sublist", func.lineno, {}, { + 'LIST':listname, + 'VAR': varblock + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('tolist')['List'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("list_tolist2", func.lineno, {}, { + "VAR": objblock + }, { + "inline": "true" + }); + } \ No newline at end of file diff --git a/mixly/boards/default_src/python/converters/logic.js b/mixly/boards/default_src/python/converters/logic.js new file mode 100644 index 00000000..17009d7b --- /dev/null +++ b/mixly/boards/default_src/python/converters/logic.js @@ -0,0 +1,15 @@ +'use strict'; + + +//目前块都在python_to_blockly.js中实现 +pbc.globalFunctionD['bool'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var numblock = py2block.convert(args[0]); + return block("logic_tobool", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/converters/math.js b/mixly/boards/default_src/python/converters/math.js new file mode 100644 index 00000000..8d7d1de3 --- /dev/null +++ b/mixly/boards/default_src/python/converters/math.js @@ -0,0 +1,389 @@ +'use strict'; + +//加减乘除 在python_to_blockly.js中实现 +//位操作 在python_to_blockly.js中实现 +function mathDecchange(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + + return block("math_dec", func.lineno, { + 'OP': mode + }, { + 'NUM': py2block.convert(args[0]) + }, { + "inline": "true" + }); + + } + + return converter; +} + +pbc.globalFunctionD['bin'] = mathDecchange('bin'); +pbc.globalFunctionD['oct'] = mathDecchange('oct'); +pbc.globalFunctionD['hex'] = mathDecchange('hex'); + +function mathTrigonometric(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + // if (args[0]._astname == "Call" + // && args[0].func._astname == "Attribute" + // && args[0].func.value._astname == "Name" + // && py2block.Name_str(args[0].func.value) == "math" + // && py2block.identifier(args[0].func.attr) == "radians" + // && args[0].args.length == 1) { + return block("math_trig", func.lineno, { + 'OP': mode + }, { + 'NUM': py2block.convert(args[0]) + }, { + "inline": "true" + }); + // } else { + // throw new Error("not implement math." + mode); + // } + + + } + + return converter; +} + +pbc.moduleFunctionD.get('math')['sin'] = mathTrigonometric('SIN'); +pbc.moduleFunctionD.get('math')['cos'] = mathTrigonometric('COS'); +pbc.moduleFunctionD.get('math')['tan'] = mathTrigonometric('TAN'); + +function mathAntiTrigonometric() { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + if (args[0]._astname == "Call" + && args[0].func._astname == "Attribute" + && args[0].func.value._astname == "Name" + && py2block.Name_str(args[0].func.value) == "math" + && (py2block.identifier(args[0].func.attr) == "asin" + || py2block.identifier(args[0].func.attr) == "acos" + || py2block.identifier(args[0].func.attr) == "atan") + && args[0].args.length == 1) { + return block("math_trig", func.lineno, { + 'OP': py2block.identifier(args[0].func.attr).toUpperCase() + }, { + 'NUM': py2block.convert(args[0].args[0]) + }, { + "inline": "true" + }); + } else { + throw new Error("not implement math.degrees"); + } + } + + return converter; +} + +pbc.moduleFunctionD.get('math')['degrees'] = mathAntiTrigonometric(); + +function mathLogOrExp(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (mode != "POW10") { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + return block("math_trig", func.lineno, { + 'OP': mode + }, { + 'NUM': py2block.convert(args[0]) + }, { + "inline": "true" + }); + } else { + if (args.length != 2) { + throw new Error("Incorrect number of arguments"); + } + return block("math_trig", func.lineno, { + 'OP': mode + }, { + 'NUM': py2block.convert(args[1]) + }, { + "inline": "true" + }); + } + } + + return converter; +} + +pbc.moduleFunctionD.get('math')['log'] = mathLogOrExp('LN'); +pbc.moduleFunctionD.get('math')['log10'] = mathLogOrExp('LOG10'); +pbc.moduleFunctionD.get('math')['exp'] = mathLogOrExp('EXP'); +pbc.moduleFunctionD.get('math')['pow'] = mathLogOrExp('POW10'); + + +function mathIntFunc(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var varblock = py2block.convert(args[0]); + return block("math_to_int", func.lineno, { + 'OP': mode + }, { + 'A': varblock + }, { + "inline": "true" + }); + } + + return converter; +} + +pbc.globalFunctionD['round'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1 && args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + if (args.length == 1){ + var varblock = py2block.convert(args[0]); + return block("math_to_int", func.lineno, { + 'OP': "round" + }, { + 'A': varblock + }, { + "inline": "true" + }); + } + if (args.length == 2){ + var varblock = py2block.convert(args[0]); + var varblock1 = py2block.convert(args[1]); + return block("math_round", func.lineno, {}, { + 'VALUE': varblock, + 'VAR': varblock1 + }, { + "inline": "true" + }); + } + +} + + +pbc.moduleFunctionD.get('math')['sqrt'] = mathIntFunc('sqrt'); +pbc.moduleFunctionD.get('math')['ceil'] = mathIntFunc('ceil'); +pbc.moduleFunctionD.get('math')['floor'] = mathIntFunc('floor'); +pbc.moduleFunctionD.get('math')['fabs'] = mathIntFunc('fabs'); + + +function mathMaxMin(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length === 2) { + if (args[0]._astname == "Call" + && args[0].func._astname == "Name" + && py2block.Name_str(args[0].func) == "max" + && py2block.Name_str(func) == "min") { + return block("math_constrain", func.lineno, {}, { + 'VALUE': py2block.convert(args[0].args[0]), + 'LOW': py2block.convert(args[0].args[1]), + 'HIGH': py2block.convert(args[1]) + }, { + "inline": "true" + }); + } else { + var ablock = py2block.convert(args[0]); + var bblock = py2block.convert(args[1]); + return block("math_max_min", func.lineno, { + 'OP': mode + }, { + 'A': ablock, + 'B': bblock + }, { + "inline": "true" + }); + } + } else if (args.length === 1) { + var argblock = py2block.convert(args[0]); + return block("list_trig", func.lineno, { + 'OP': mode.toUpperCase() + }, { + 'data': argblock + }, { + "inline": "true" + }); + } else { + throw new Error("Incorrect number of arguments"); + } + } + return converter; +} + +pbc.globalFunctionD['max'] = mathMaxMin('max'); +pbc.globalFunctionD['min'] = mathMaxMin('min'); + + +function mathRandom(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 2) { + throw new Error("Incorrect number of arguments"); + } + var fromblock = py2block.convert(args[0]); + var toblock = py2block.convert(args[1]); + return block("math_random", func.lineno, { + 'TYPE': mode + }, { + 'FROM': fromblock, + 'TO': toblock + }, { + "inline": "true" + }); + } + + return converter; +} + +pbc.moduleFunctionD.get('random')['randint'] = mathRandom('int'); +pbc.moduleFunctionD.get('random')['uniform'] = mathRandom('float'); + +pbc.moduleFunctionD.get('random')['seed'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var varblock = py2block.convert(args[0]); + return [block("math_random_seed", func.lineno, {}, { + 'NUM': varblock + }, { + "inline": "true" + })]; +} + +function radixToEng(num) { + if (num == 2) { + return 'two'; + } else if (num == 8) { + return 'eight'; + } else if (num == 10) { + return 'ten'; + } else if (num == 16) { + return 'sixteen'; + } else { + return "unknown"; + } +} + +pbc.globalFunctionD['int'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length == 1) { + var paramblock = py2block.convert(args[0]); + if (args[0]._astname == "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "str") { + paramblock = py2block.convert(args[0].args[0]); + }else if(args[0]._astname == "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "input"){ + if(pbc.board == pbc.MIXPY) { + paramblock = py2block.convert(args[0].args[0]); + return block("inout_type_input", func.lineno, { + "DIR": "int" + }, { + 'VAR': paramblock + }, { + "inline": "true" + }); + } + }else if(args[0]._astname == "Call" && args[0].func._astname == "Attribute" && args[0].func.attr.v == "input"){ + if(pbc.board == pbc.MIXPY) { + paramblock = py2block.convert(args[0].args[0]); + return block("inout_type_input", func.lineno, { + "DIR": "int" + }, { + 'VAR': paramblock + }, { + "inline": "true" + }); + } + } + return block("text_to_number", func.lineno, { + 'TOWHAT': "int" + }, { + 'VAR': paramblock, + }, { + "inline": "true" + }); + } else if (args.length == 2) { + if (args[0]._astname == "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "str" + && args[1]._astname == "Num") { + var paramblock = py2block.convert(args[0].args[0]); + return block("math_number_base_conversion", func.lineno, { + 'OP': radixToEng(args[1].n.v), + 'OP2': 'ten' + }, { + 'NUM': paramblock, + }, { + "inline": "true" + }); + } + } + throw new Error("Incorrect number of arguments"); +} + + +/*function radix(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + if (args[0]._astname == "Call" + && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "int" + && args[0].args[0]._astname == "Call" && args[0].args[0].func._astname == "Name" && py2block.Name_str(args[0].args[0].func) == "str") { + var paramblock = py2block.convert(args[0].args[0].args[0]); + return block("math_number_base_conversion", func.lineno, { + 'OP': radixToEng(args[0].args[1].n.v), + 'OP2': mode + }, { + 'NUM': paramblock, + }, { + "inline": "true" + }); + } + } + return converter; +} + +pbc.globalFunctionD['hex'] = radix('sixteen'); +pbc.globalFunctionD['oct'] = radix('eight'); +pbc.globalFunctionD['bin'] = radix('two');*/ + + +pbc.globalFunctionD['math_map'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 5) { + throw new Error("Incorrect number of arguments"); + } + return block("math_map", func.lineno, {}, { + 'NUM': py2block.convert(args[0]), + 'fromLow': py2block.convert(args[1]), + 'fromHigh': py2block.convert(args[2]), + 'toLow': py2block.convert(args[3]), + 'toHigh': py2block.convert(args[4]) + }, { + "inline": "true" + }); +} + +pbc.globalFunctionD['abs'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return [block("math_to_int", func.lineno, { + "OP":'fabs' + }, { + 'A': argblock + }, { + "inline": "true" + })]; +} + +function mathConstant(py2block, node, value, attr) { + return block('math_constant', node.lineno, { + 'CONSTANT': value + }, {}); +} + +pbc.moduleAttrD.get('math')['pi'] = mathConstant; +pbc.moduleAttrD.get('math')['e'] = mathConstant; \ No newline at end of file diff --git a/mixly/boards/default_src/python/converters/set.js b/mixly/boards/default_src/python/converters/set.js new file mode 100644 index 00000000..5e17fa35 --- /dev/null +++ b/mixly/boards/default_src/python/converters/set.js @@ -0,0 +1,180 @@ +'use strict'; + +pbc.assignD.get('Set')['check_assign'] = function (py2block, node, targets, value) { + if (value._astname === "Set") + return true; + return false; +} + +pbc.assignD.get('Set')['create_block'] = function (py2block, node, targets, value) { + return block("set_create_with", node.lineno, { + 'VAR': py2block.Name_str(targets[0]) + }, + py2block.convertElements("ADD", value.elts), { + "inline": "false", + }, { + "@items": value.elts.length + }); +} + +//len在text里实现 + +pbc.objectFunctionD.get('pop')['Set'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length === 0) { + var popblock = py2block.convert(func.value); + return block("set_pop", func.lineno, {}, { + "SET":popblock + }, { + "inline": "true" + }); + }else if(args.length === 1){ + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("lists_pop", func.lineno, {}, { + "LIST":objblock, + "VALUE":argblock + }, { + "inline": "true" + }); + }else{ + throw new Error("Incorrect number of arguments"); + } + +} + + +//tuple(mytuple), set(mytup)在lists.js中实现 + +function setOperate(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("set_operate", func.lineno, { + 'OPERATE': mode, + }, { + "SET1": objblock, + "SET2": argblock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('union')['Set'] = setOperate('union'); +pbc.objectFunctionD.get('intersection')['Set'] = setOperate('intersection'); +pbc.objectFunctionD.get('difference')['Set'] = setOperate('difference'); + + +pbc.objectFunctionD.get('update')['Set'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return [block("set_update", func.lineno, {}, { + "SET": objblock, + "VAR": argblock + }, { + "inline": "true" + })]; +}; + + +function setOperateUpdate(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return [block("set_operate_update", func.lineno, { + 'OPERATE': mode, + }, { + "SET1": objblock, + "SET2": argblock + }, { + "inline": "true" + })]; + } + return converter; +} + + + +pbc.objectFunctionD.get('difference_update')['Set'] = setOperateUpdate('difference_update'); +pbc.objectFunctionD.get('intersection_update')['Set'] = setOperateUpdate('intersection_update'); + + +function setAddDiscard(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return [block("set_add_discard", func.lineno, { + 'OPERATE':mode, + }, { + "SET":objblock, + "data":argblock + }, { + "inline": "true" + })]; + } + return converter; +} + +pbc.objectFunctionD.get('add')['Set'] = setAddDiscard('add'); +pbc.objectFunctionD.get('discard')['Set'] = setAddDiscard('discard'); + + +function setSub(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("set_sub", func.lineno, { + 'OPERATE':mode, + }, { + "SET1":objblock, + "SET2":argblock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.globalFunctionD['set'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length > 1) { + throw new Error("Incorrect number of arguments"); + } + if (args.length ==0){ + return block("set_create_with_noreturn", node.lineno, {},{} + , { + "inline": "true", + }, { + "@items": 0 + }); + } + if (args.length ==1){ + var numblock = py2block.convert(args[0]); + return block("set_toset", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); + } +} + + + +pbc.objectFunctionD.get('issubset')['Set'] = setSub('issubset'); +pbc.objectFunctionD.get('issuperset')['Set'] = setSub('issuperset'); + diff --git a/mixly/boards/default_src/python/converters/storage.js b/mixly/boards/default_src/python/converters/storage.js new file mode 100644 index 00000000..6ce6415a --- /dev/null +++ b/mixly/boards/default_src/python/converters/storage.js @@ -0,0 +1,359 @@ +'use strict'; + +var fileClass = 'open'; + + + + +pbc.globalFunctionD['open'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + if (keywords.length == 0) { + var varblock = py2block.convert(args[0]); + var mode = py2block.Str_value(args[1]); + return block("storage_fileopen_new", node.lineno, { + "MODE":mode + }, { + "FILENAME":varblock + }); + } + if (keywords.length == 1) { + var varblock = py2block.convert(args[0]); + var mode = py2block.Str_value(args[1]); + var code = py2block.Str_value(keywords[0].value); + return block("storage_fileopen_new_encoding", node.lineno, { + "MODE":mode, + "CODE":code + }, { + "FILENAME":varblock + }); + } + +} + +pbc.objectFunctionD.get('write')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var fileblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return [block("storage_file_write", func.lineno, {}, { + "FILE" : fileblock, + "data" :argblock + }, { + "inline": "true" + })]; +} + + +pbc.objectFunctionD.get('read')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length == 1) { + var fileblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("storage_get_contents", func.lineno, { + "MODE":"read" + }, { + "FILE" : fileblock, + "SIZE" : argblock + }, { + "inline": "true" + }); + } + if (args.length == 0) { + var fileblock = py2block.convert(func.value); + return block("storage_get_contents_without_para", func.lineno, { + "MODE":"read" + }, { + "FILE" : fileblock + }, { + "inline": "true" + }); + } + else{ + throw new Error("Incorrect number of arguments"); + } +} + + +pbc.objectFunctionD.get('readline')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length == 1) { + var fileblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("storage_get_contents", func.lineno, { + "MODE":"readline" + }, { + "FILE" : fileblock, + "SIZE" : argblock + }, { + "inline": "true" + }); + } + if (args.length == 0) { + var fileblock = py2block.convert(func.value); + return block("storage_get_contents_without_para", func.lineno, { + "MODE":"readline" + }, { + "FILE" : fileblock + }, { + "inline": "true" + }); + } + else{ + throw new Error("Incorrect number of arguments"); + } +} + +pbc.objectFunctionD.get('readlines')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length == 1) { + var fileblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("storage_get_contents", func.lineno, { + "MODE":"readlines" + }, { + "FILE" : fileblock, + "SIZE" : argblock + }, { + "inline": "true" + }); + } + if (args.length == 0) { + var fileblock = py2block.convert(func.value); + return block("storage_get_contents_without_para", func.lineno, { + "MODE":"readlines" + }, { + "FILE" : fileblock + }, { + "inline": "true" + }); + } + else{ + throw new Error("Incorrect number of arguments"); + } +} + + +pbc.objectFunctionD.get('writable')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var fileblock = py2block.convert(func.value); + return block("storage_can_write_ornot", func.lineno, {}, { + "FILE" : fileblock, + }, { + "inline": "true" + }); +} + + +pbc.objectFunctionD.get('name')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var fileblock = py2block.convert(func.value); + return block("storage_get_filename", func.lineno, {}, { + "FILE" : fileblock + }, { + "inline": "true" + }); +} + + +pbc.objectFunctionD.get('close')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var fileblock = py2block.convert(func.value); + return [block("storage_close_file", func.lineno, {}, { + "FILE" : fileblock + }, { + "inline": "true" + })]; +} + + +pbc.moduleFunctionD.get('os')['listdir'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + return block("storage_list_all_files", func.lineno, {}, { + }, { + "inline": "true" + }); +} + + +pbc.moduleFunctionD.get('os')['remove'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return [block("storage_delete_file", func.lineno, {"MODE":"remove"}, { + "FILE" : argblock + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('os')['removedirs'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return [block("storage_delete_file", func.lineno, {"MODE":"removedirs"}, { + "FILE" : argblock + }, { + "inline": "true" + })]; +} +pbc.moduleFunctionD.get('os')['size'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return block("storage_get_file_size", func.lineno, {}, { + "FILE" : argblock + }, { + "inline": "true" + }); +} + +pbc.objectFunctionD.get('seek')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var fileblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + if(args[1].n.v=="0"){ + var mode = "start"; + } + else if(args[1].n.v=="1"){ + var mode = "current"; + } + else{ + var mode = "end"; + } + return [block("storage_file_seek", func.lineno, { + "MODE": mode + }, { + "FILE" : fileblock, + "SIZE" : argblock + }, { + "inline": "true" + })]; +} + +pbc.objectFunctionD.get('tell')[fileClass] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var fileblock = py2block.convert(func.value); + return block("storage_file_tell", func.lineno, { + }, { + "FILE" : fileblock, + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('os')['chdir'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return [block("storage_change_dir", func.lineno, {}, { + "FILE" : argblock + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('os')['getcwd'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + return block("storage_get_current_dir", func.lineno, {}, { + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('os')['mkdir'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var fun = func.attr.v; + var argblock = py2block.convert(args[0]); + return [block("storage_make_dir", func.lineno, {"MODE":fun}, { + "PATH" : argblock + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('os')['makedirs'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var fun = func.attr.v; + var argblock = py2block.convert(args[0]); + return [block("storage_make_dir", func.lineno, {"MODE":fun}, { + "PATH" : argblock + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('os')['rename'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + var arg1block = py2block.convert(args[1]); + return [block("storage_rename", func.lineno, {}, { + "FILE" : argblock, + "NEWFILE":arg1block + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('os')['isfile'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var fun = func.attr.v; + var argblock = py2block.convert(args[0]); + return [block("storage_is_file", func.lineno, {"MODE":fun}, { + "FILE" : argblock + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('os')['startfile'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var fun = func.attr.v; + var argblock = py2block.convert(args[0]); + return [block("storage_open_file_with_os", func.lineno, {"MODE":fun}, { + "fn" : argblock + }, { + "inline": "true" + })]; +} + +pbc.moduleFunctionD.get('os')['isdir'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var fun = func.attr.v; + var argblock = py2block.convert(args[0]); + return [block("storage_is_file", func.lineno, {"MODE":fun}, { + "FILE" : argblock + }, { + "inline": "true" + })]; +} + diff --git a/mixly/boards/default_src/python/converters/text.js b/mixly/boards/default_src/python/converters/text.js new file mode 100644 index 00000000..bb08d6e1 --- /dev/null +++ b/mixly/boards/default_src/python/converters/text.js @@ -0,0 +1,377 @@ +'use strict'; + +//01."text" 在 python_to_blockly.js实现 + +//02.str('Hello') + str('Mixly') 在 python_to_blockly.js实现 + +//03.int(str('123'))这种形式的,在math.js实现 +function numConvert(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if ((mode != 'b' && args.length != 1) || (mode == 'b' && args.length != 2)) { + throw new Error("Incorrect number of arguments"); + } + var paramblock = py2block.convert(args[0]); + if (args[0]._astname == "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "str") { + paramblock = py2block.convert(args[0].args[0]); + }else if(args[0]._astname == "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "input"){ + if(pbc.board == pbc.MIXPY) { + paramblock = py2block.convert(args[0].args[0]); + return block("inout_type_input", func.lineno, { + "DIR": "float" + }, { + 'VAR': paramblock + }, { + "inline": "true" + }); + } + }else if(args[0]._astname == "Call" && args[0].func._astname == "Attribute" && args[0].func.attr.v == "input"){ + if(pbc.board == pbc.MIXPY) { + paramblock = py2block.convert(args[0].args[0]); + return block("inout_type_input", func.lineno, { + "DIR": "float" + }, { + 'VAR': paramblock + }, { + "inline": "true" + }); + } + } + return block("text_to_number", func.lineno, { + 'TOWHAT': mode + }, { + 'VAR': paramblock, + }, { + "inline": "false" + }); + } + return converter; +} + +pbc.globalFunctionD['float'] = numConvert('float'); +pbc.globalFunctionD['bytes'] = numConvert('b'); + + +pbc.globalFunctionD['chr'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var numblock = py2block.convert(args[0]); + return block("ascii_to_char", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); +} + + +pbc.globalFunctionD['ord'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var numblock = py2block.convert(args[0]); + return block("char_to_ascii", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); +} + + +pbc.globalFunctionD['str'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var numblock = py2block.convert(args[0]); + return block("number_to_text", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); +} + +pbc.globalFunctionD['len'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var numblock = py2block.convert(args[0]); + return block("text_length", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); +} + + +// 'mixly'[0]这种形式的,在python_to_blockly.js中实现 + + +pbc.moduleFunctionD.get('random')['choice'] = function (py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + var argAstname = args[0]._astname; + if(args[0]._astname == "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "str"){ + argblock = py2block.convert(args[0].args[0]); + argAstname = "Str"; + } + if(argAstname == "Str"){ + return block('text_random_char', func.lineno, {}, { + 'VAR':argblock + }, { + "inline": "true" + }); + }else{ + return block('lists_get_random_item', func.lineno, {}, { + 'LIST':argblock + }, { + "inline": "true" + }); + } +} + + +//str('123') == str('234')这种形式的,在python_to_blockly.js中实现 + +function startEndWithStr(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + if(func.value._astname == "Call" && func.value.func._astname == "Name" && py2block.Name_str(func.value.func) == "str"){ + objblock = py2block.convert(func.value.args[0]); + } + var argblock = py2block.convert(args[0]); + if(args[0]._astname == "Call" && args[0].func._astname == "Name" && py2block.Name_str(args[0].func) == "str"){ + argblock = py2block.convert(args[0].args[0]); + } + return block('text_equals_starts_ends', func.lineno, { + 'DOWHAT':mode + }, { + 'STR1':objblock, + 'STR2':argblock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('startswith')['Str'] = startEndWithStr('startswith'); +pbc.objectFunctionD.get('endswith')['Str'] = startEndWithStr('endswith'); + + +// 'mixly'[0:8]这种形式的,在python_to_blockly.js中实现 +function strTitle(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var textblock = py2block.convert(func.value); + return block("text_capital", func.lineno, { + 'CAPITAL': mode, + }, { + "VAR": textblock, + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('upper')['Str'] = strTitle('upper'); +pbc.objectFunctionD.get('title')['Str'] = strTitle('title'); +pbc.objectFunctionD.get('lower')['Str'] = strTitle('lower'); +pbc.objectFunctionD.get('swapcase')['Str'] = strTitle('swapcase'); +pbc.objectFunctionD.get('capitalize')['Str'] = strTitle('capitalize'); + +function strencode(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var textblock = py2block.convert(func.value); + return block("text_to_number", func.lineno, { + 'TOWHAT': mode, + }, { + "VAR": textblock, + }, { + "inline": "true" + }); + } + return converter; +} +pbc.objectFunctionD.get('encode')['Str'] = strencode('b'); + + +function textStrip(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 0) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + return block("text_strip", func.lineno, { + 'TOWHAT': mode, + }, { + "VAR": objblock, + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('strip')['Str'] = textStrip('strip'); +pbc.objectFunctionD.get('lstrip')['Str'] = textStrip('lstrip'); +pbc.objectFunctionD.get('rstrip')['Str'] = textStrip('rstrip'); + + + +function textAlign(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock1 = py2block.convert(args[0]); + var argblock2 = py2block.convert(args[1]); + return block("text_center", func.lineno, { + 'CENTER': mode, + }, { + "VAR": objblock, + "WID": argblock1, + "Symbol": argblock2 + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('ljust')['Str'] = textAlign('ljust'); +pbc.objectFunctionD.get('center')['Str'] = textAlign('center'); +pbc.objectFunctionD.get('rjust')['Str'] = textAlign('rjust'); + + +pbc.objectFunctionD.get('split')['Str'] = function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("text_split", func.lineno, { + }, { + "VAR": objblock, + "VAL": argblock + }, { + "inline": "true" + }); + } + +pbc.objectFunctionD.get('replace')['Str'] = function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 2) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock1 = py2block.convert(args[0]); + var argblock2 = py2block.convert(args[1]); + return block("text_replace", func.lineno, { + }, { + "VAR": objblock, + "STR1": argblock1, + "STR2": argblock2 + }, { + "inline": "true" + }); + } + +pbc.objectFunctionD.get('find')['Str'] = function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("text_find", func.lineno, { + }, { + "VAR": objblock, + "STR": argblock + }, { + "inline": "true" + }); + } + +pbc.objectFunctionD.get('join')['Str'] = function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + var argblock = py2block.convert(args[0]); + return block("text_join_seq", func.lineno, { + }, { + "VAR": objblock, + "LIST": argblock + }, { + "inline": "true" + }); + } + +pbc.objectFunctionD.get('format')['Str'] = function converter(py2block, func, args, keywords, starargs, kwargs, node) { + var objblock = py2block.convert(func.value); + var d = py2block.convertElements("ADD", args); + d['VAR'] = objblock; + return block("text_format_noreturn", node.lineno, { + }, d, { + "inline": "true", + }, { + "@items":args.length + }); + } + + + +function strEncodeDecode(mode){ + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var objblock = py2block.convert(func.value); + + return block("text_encode", func.lineno, { + 'DIR': mode, + 'CODE':args[0].s.v + }, { + "VAR": objblock, + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.objectFunctionD.get('encode')['Str'] = strEncodeDecode('encode'); +pbc.objectFunctionD.get('decode')['Str'] = strEncodeDecode('decode'); + +pbc.globalFunctionD['eval'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length != 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return block("text_eval", func.lineno, {}, { + "VAR":argblock + }, { + "inline": "true" + }); +} + +pbc.moduleFunctionD.get('os')['system'] = function (py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var varblock = py2block.convert(args[0]); + return [block("os_system", func.lineno, {}, { + 'VAR': varblock + }, { + "inline": "true" + })]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/converters/tuple.js b/mixly/boards/default_src/python/converters/tuple.js new file mode 100644 index 00000000..cdc2d219 --- /dev/null +++ b/mixly/boards/default_src/python/converters/tuple.js @@ -0,0 +1,47 @@ +'use strict'; + +pbc.assignD.get('Tuple')['check_assign'] = function (py2block, node, targets, value) { + if (value._astname === "Tuple") + return true; + return false; +} + +pbc.assignD.get('Tuple')['create_block'] = function (py2block, node, targets, value) { + return block("tuple_create_with", node.lineno, { + 'VAR': py2block.Name_str(targets[0]) + }, + py2block.convertElements("ADD", value.elts), { + "inline": elts.length < 4 ? "false" : "true", + }, { + "@items": value.elts.length + }); +} + +//mytup[0]在python_to_blockly.py中实现 +//len在text里实现 + +//max/min在math里已实现 + +//list(mytuple), set(mytup)在lists.js中实现 + +pbc.globalFunctionD['tuple'] = function(py2block, func, args, keywords, starargs, kwargs, node){ + if (args.length > 1) { + throw new Error("Incorrect number of arguments"); + } + if (args.length ==0){ + return block("tuple_create_with_noreturn", node.lineno, {},{} + , { + "inline": "true", + }, { + "@items": 0 + }); + } + if (args.length ==1){ + var numblock = py2block.convert(args[0]); + return block("tuple_totuple", func.lineno, {}, { + 'VAR': numblock, + }, { + "inline": "false" + }); + } +} diff --git a/mixly/boards/default_src/python/converters/variables.js b/mixly/boards/default_src/python/converters/variables.js new file mode 100644 index 00000000..7b458ad2 --- /dev/null +++ b/mixly/boards/default_src/python/converters/variables.js @@ -0,0 +1,39 @@ +'use strict'; + +pbc.globalFunctionD['dict'] = function converter(py2block, func, args, keywords, starargs, kwargs, node) { + var paramblock = py2block.convert(args[0]); + return block("variables_change", func.lineno, { + 'OP': 'dict' + }, { + 'MYVALUE': paramblock, + }, { + "inline": "false" + }); +} + +function TypeConvert(mode) { + function converter(py2block, func, args, keywords, starargs, kwargs, node) { + if (args.length !== 1) { + throw new Error("Incorrect number of arguments"); + } + var argblock = py2block.convert(args[0]); + return block("variables_change", func.lineno, { + "OP":mode + }, { + 'MYVALUE': argblock + }, { + "inline": "true" + }); + } + return converter; +} + +pbc.globalFunctionD['int'] = TypeConvert('int'); +pbc.globalFunctionD['float'] = TypeConvert('float'); +pbc.globalFunctionD['bool'] = TypeConvert('bool'); +// pbc.globalFunctionD['complex'] = TypeConvert('complex'); +pbc.globalFunctionD['str'] = TypeConvert('str'); +pbc.globalFunctionD['list'] = TypeConvert('list'); +pbc.globalFunctionD['tuple'] = TypeConvert('tuple'); +pbc.globalFunctionD['set'] = TypeConvert('set'); +pbc.globalFunctionD['dict'] = TypeConvert('dict'); \ No newline at end of file diff --git a/mixly/boards/default_src/python/export.js b/mixly/boards/default_src/python/export.js new file mode 100644 index 00000000..0ce0638b --- /dev/null +++ b/mixly/boards/default_src/python/export.js @@ -0,0 +1,65 @@ +import * as PythonVariablesBlocks from './blocks/variables'; +import * as PythonControlBlocks from './blocks/control'; +import * as PythonMathBlocks from './blocks/math'; +import * as PythonTextBlocks from './blocks/text'; +import * as PythonListsBlocks from './blocks/lists'; +import * as PythonDictsBlocks from './blocks/dicts'; +import * as PythonLogicBlocks from './blocks/logic'; +import * as PythonStorageBlocks from './blocks/storage'; +import * as PythonProceduresBlocks from './blocks/procedures'; +import * as PythonTupleBlocks from './blocks/tuple'; +import * as PythonSetBlocks from './blocks/set'; +import * as PythonHtmlBlocks from './blocks/html'; +import * as PythonUtilityBlocks from './blocks/utility'; + +import * as PythonVariablesGenerators from './generators/variables'; +import * as PythonControlGenerators from './generators/control'; +import * as PythonMathGenerators from './generators/math'; +import * as PythonTextGenerators from './generators/text'; +import * as PythonListsGenerators from './generators/lists'; +import * as PythonDictsGenerators from './generators/dicts'; +import * as PythonLogicGenerators from './generators/logic'; +import * as PythonStorageGenerators from './generators/storage'; +import * as PythonProceduresGenerators from './generators/procedures'; +import * as PythonTupleGenerators from './generators/tuple'; +import * as PythonSetGenerators from './generators/set'; +import * as PythonHtmlGenerators from './generators/html'; +import * as PythonUtilityGenerators from './generators/utility'; + +import Names from './others/names'; +import Procedures from './others/procedures'; +import Variables from './others/variables'; +import { Python } from './python_generator'; + +export { + PythonVariablesBlocks, + PythonControlBlocks, + PythonMathBlocks, + PythonTextBlocks, + PythonListsBlocks, + PythonDictsBlocks, + PythonLogicBlocks, + PythonStorageBlocks, + PythonProceduresBlocks, + PythonTupleBlocks, + PythonSetBlocks, + PythonHtmlBlocks, + PythonUtilityBlocks, + PythonVariablesGenerators, + PythonControlGenerators, + PythonMathGenerators, + PythonTextGenerators, + PythonListsGenerators, + PythonDictsGenerators, + PythonLogicGenerators, + PythonStorageGenerators, + PythonProceduresGenerators, + PythonTupleGenerators, + PythonSetGenerators, + PythonHtmlGenerators, + PythonUtilityGenerators, + Names, + Procedures, + Variables, + Python +}; \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/blynk.js b/mixly/boards/default_src/python/generators/blynk.js new file mode 100644 index 00000000..61d9bc57 --- /dev/null +++ b/mixly/boards/default_src/python/generators/blynk.js @@ -0,0 +1,89 @@ +import * as Blockly from 'blockly/core'; + +// 物联网-wifi信息 +export const blynk_server = function (_, generator) { + var wifi_ssid = generator.valueToCode(this, 'wifi_ssid', generator.ORDER_ATOMIC); + var wifi_pass = generator.valueToCode(this, 'wifi_pass', generator.ORDER_ATOMIC); + generator.definitions_.import_time = "import network,time,BlynkLib"; + var code; + code = "wlan = network.WLAN(network.STA_IF)\n"; + code += "wlan.active(True)\n"; + code += "if not wlan.isconnected():\n"; + code += " print('connecting to network...')\n"; + code += " wlan.connect(" + wifi_ssid + "," + wifi_pass + ")\n"; + code += " while not wlan.isconnected():\n"; + code += " pass\n"; + code += "print('network config:', wlan.ifconfig())\n"; + code += "BLYNK_AUTH='" + "auth_key" + "'\n"; + code += "blynk = BlynkLib.Blynk(BLYNK_AUTH)\n" + code += "while True:\n" + code += " blynk.run()\n" + code += " pass\n" + return code; +} + +// 物联网-wifi信息 +export const blynk_iot_get_data = function (_, generator) { + var Vpin = this.getFieldValue('Vpin'); + var args = []; + for (var x = 0; x < this.arguments_.length; x++) { + args[x] = generator.valueToCode(this, 'ARG' + x, generator.ORDER_NONE) || 'null'; + } + var code = '(a' + args.join(', ') + ');\n'; + var branch = generator.statementToCode(this, 'STACK'); + if (generator.INFINITE_LOOP_TRAP) { + branch = generator.INFINITE_LOOP_TRAP.replace(/%1/g, '\'' + this.id + '\'') + branch; + } + var args = []; + for (var x = 0; x < this.arguments_.length; x++) { + args[x] = this.argumentstype_[x] + ' ' + generator.variableDB_.getName(this.arguments_[x], Blockly.Variables.NAME_TYPE); + } + var GetDataCode = ""; + if (this.arguments_.length == 1) { + GetDataCode = generator.variableDB_.getName(this.arguments_[0], Blockly.Variables.NAME_TYPE); + if (this.argumentstype_[0] == "int") + GetDataCode += "= param.asInt();\n" + else if (this.argumentstype_[0] == "String") + GetDataCode += "= param.asStr();\n" + else if (this.argumentstype_[0] == "long") + GetDataCode += "= param.asDouble();\n" + else if (this.argumentstype_[0] == "float") + GetDataCode += "= param.asFloat();\n" + else if (this.argumentstype_[0] == "boolean") + GetDataCode += "= param.asInt();\n" + else if (this.argumentstype_[0] == "byte") + GetDataCode += "= param.asStr();\n" + else if (this.argumentstype_[0] == "char") + GetDataCode += "= param.asStr();\n" + } + else { + for (var x = 0; x < this.arguments_.length; x++) { + args[x] = this.argumentstype_[x] + ' ' + generator.variableDB_.getName(this.arguments_[x], Blockly.Variables.NAME_TYPE); + + GetDataCode += generator.variableDB_.getName(this.arguments_[x], Blockly.Variables.NAME_TYPE); + if (this.argumentstype_[x] == "int") + GetDataCode += "= param[" + x + "].asInt();\n" + else if (this.argumentstype_[x] == "String") + GetDataCode += "= param[" + x + "].asStr();\n" + else if (this.argumentstype_[x] == "long") + GetDataCode += "= param[" + x + "].asDouble();\n" + else if (this.argumentstype_[x] == "float") + GetDataCode += "= param[" + x + "].asFloat();\n" + else if (this.argumentstype_[x] == "boolean") + GetDataCode += "= param[" + x + "].asInt();\n" + else if (this.argumentstype_[x] == "byte") + GetDataCode += "= param[" + x + "].asStr();\n" + else if (this.argumentstype_[x] == "char") + GetDataCode += "= param[" + x + "].asStr();\n" + } + } + + if (this.arguments_.length > 0) + generator.definitions_[args] = args.join(';\n') + ";"; + var code = ' BLYNK_WRITE(' + Vpin + ') {\n' + GetDataCode + + branch + '}\n'; + // var code = 'BLYNK_WRITE(' + Vpin+ ') {\n'+variable+" = param.as"+datatype+"();\n"+branch+'}\n'; + code = generator.scrub_(this, code); + generator.definitions_[Vpin] = code; + return null; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/class.js b/mixly/boards/default_src/python/generators/class.js new file mode 100644 index 00000000..e462ecef --- /dev/null +++ b/mixly/boards/default_src/python/generators/class.js @@ -0,0 +1,147 @@ +import * as Blockly from 'blockly/core'; + +export const class_make = function (_, generator) { + var text_name = this.getFieldValue('VAR') || 'None'; + var statements_data = generator.statementToCode(this, 'data'); + var code = 'class ' + text_name + ':\n' + statements_data; + return code; +} + +export const class_make_with_base = function (_, generator) { + var text_name = this.getFieldValue('VAR') || 'None'; + var name = generator.valueToCode(this, 'NAME', generator.ORDER_ASSIGNMENT) || 'None'; + var statements_data = generator.statementToCode(this, 'data'); + var code = ''; + if (name == 'None') + code = 'class ' + text_name + ':\n' + statements_data; + else + code = 'class ' + text_name + '(' + name + '):\n' + statements_data; + return code; +} + +export const class_get = function (_, generator) { + var code = this.getFieldValue('VAR') || 'None'; + return [code, generator.ORDER_ATOMIC]; +} + +export const property_set = function (_, generator) { + var argument0 = generator.valueToCode(this, 'VALUE', generator.ORDER_ASSIGNMENT) || 'None'; + var argument1 = generator.valueToCode(this, 'DATA', generator.ORDER_ASSIGNMENT) || 'None'; + var varName = this.getFieldValue('VAR') || 'None'; + return argument0 + '.' + varName + ' = ' + argument1 + '\n'; +} + +export const property_get = function (_, generator) { + var argument0 = generator.valueToCode(this, 'VALUE', generator.ORDER_ASSIGNMENT) || 'None'; + var code = this.getFieldValue('VAR') || 'None'; + return [argument0 + '.' + code, generator.ORDER_ATOMIC]; +} + +export const object_set = function (_, generator) { + var text_name = this.getFieldValue('VAR10') || 'None'; + var text_new_name = this.getFieldValue('VAR11') || 'None'; + var code = new Array(this.itemCount_); + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, generator.ORDER_NONE) || 'None'; + } + var code = text_new_name + ' = ' + text_name + '(' + code.join(',') + ')\n'; + return code; +} + +export const object_get = function (_, generator) { + var code = this.getFieldValue('VAR') || 'None'; + return [code, generator.ORDER_ATOMIC]; +} + +export const method_procedures_defreturn = function (_, generator) { + // Define a procedure with a return value. + //var funcName = generator.variableDB_.getName(this.getFieldValue('NAME'), + // Blockly.Class_Test.NAME_TYPE); + var funcName = this.getFieldValue('NAME') || 'None'; + var branch = generator.statementToCode(this, 'STACK') || ' pass\n'; + if (generator.INFINITE_LOOP_TRAP) { + branch = generator.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + this.id + '\'') + branch; + } + var returnValue = generator.valueToCode(this, 'RETURN', + generator.ORDER_NONE) || ''; + //var type=this.getFieldValue('TYPE'); + if (returnValue) { + returnValue = ' return ' + returnValue + '\n'; + } + //var returnType = returnValue ? type : 'void'; + var args = []; + for (var x = 0; x < this.arguments_.length; x++) { + var varName = generator.variableDB_.getName(this.arguments_[x], Blockly.Variables.NAME_TYPE); + args[x] = varName; + } + var code = ''; + //if(this.arguments_.length) + code = 'def ' + funcName + '(' + args.join(', ') + '):\n' + + branch + returnValue + '\n'; + //code = generator.scrub_(this, code); + //generator.setups_[funcName] = code; + return code; +} + +export const method_procedures_defnoreturn = method_procedures_defreturn; + +export const method_procedures_callreturn = function (_, generator) { + var argument1 = generator.valueToCode(this, 'DATA', generator.ORDER_ASSIGNMENT) || 'None'; + // Call a procedure with a return value. + //var funcName = generator.variableDB_.getName(this.getFieldValue('NAME'), + // Blockly.Class_Test.NAME_TYPE); + var funcName = this.getFieldValue('NAME'); + var args = []; + for (var x = 0; x < this.arguments_.length - 1; x++) { + args[x] = generator.valueToCode(this, 'ARG' + (x + 1), + generator.ORDER_NONE) || 'null'; + } + var code = argument1 + '.' + funcName + '(' + args.join(', ') + ')'; + return [code, generator.ORDER_UNARY_POSTFIX]; +} + +export const method_procedures_callnoreturn = function (_, generator) { + var argument1 = generator.valueToCode(this, 'DATA', generator.ORDER_ASSIGNMENT) || 'None'; + // Call a procedure with no return value. + //var funcName = generator.variableDB_.getName(this.getFieldValue('NAME'), + // Blockly.Class_Test.NAME_TYPE); + var funcName = this.getFieldValue('NAME'); + var args = []; + for (var x = 0; x < this.arguments_.length - 1; x++) { + args[x] = generator.valueToCode(this, 'ARG' + (x + 1), + generator.ORDER_NONE) || 'null'; + } + var code = argument1 + '.' + funcName + '(' + args.join(', ') + ')\n'; + return code; +} + +export const method_procedures_ifreturn = function (_, generator) { + // Conditionally return value from a procedure. + var condition = generator.valueToCode(this, 'CONDITION', + generator.ORDER_NONE) || 'False'; + var code = 'if (' + condition + ') :\n'; + if (this.hasReturnValue_) { + var value = generator.valueToCode(this, 'VALUE', + generator.ORDER_NONE) || 'None'; + code += ' return ' + value; + } else { + code += ' return None'; + } + code += '\n'; + return code; +} + +export const method_procedures_return = function (_, generator) { + // Conditionally return value from a procedure. + var code = "" + if (this.hasReturnValue_) { + var value = generator.valueToCode(this, 'VALUE', + generator.ORDER_NONE) || 'None'; + code += 'return ' + value; + } else { + code += 'return None'; + } + code += '\n'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/control.js b/mixly/boards/default_src/python/generators/control.js new file mode 100644 index 00000000..602c5c9a --- /dev/null +++ b/mixly/boards/default_src/python/generators/control.js @@ -0,0 +1,296 @@ +import * as Blockly from 'blockly/core'; +import { Boards } from 'mixly'; + +export const controls_main = function (a, generator) { + var d = generator.statementToCode(a, "DO"), + d = generator.addLoopTrap(d, a.id) || generator.PASS; + return "if __name__ == '__main__':\n" + d; +} + +export const base_setup = function (_, generator) { + var branch = generator.statementToCode(this, 'DO'); + branch = branch.replace(/(^\s*)|(\s*$)/g, "").replace(/\n {4}/g, '\n');//去除两端空格 + if (branch.endsWith('\n')) { + generator.setups_['setup_setup'] = branch; + } + else { + generator.setups_['setup_setup'] = branch + '\n'; + } + return ''; +} + +// ok +export const controls_if = function (a, generator) { + var b = 0, + c = "", + d, + e; + do + e = generator.valueToCode(a, "IF" + b, generator.ORDER_NONE) || "False", d = generator.statementToCode(a, "DO" + b) || generator.PASS, c += (0 == b ? "if " : "elif ") + e + ":\n" + d, ++b; + while (a.getInput("IF" + b)); + a.getInput("ELSE") && (d = generator.statementToCode(a, "ELSE") || generator.PASS, c += "else:\n" + d); + return c +} + +export const controls_try_finally = function (_, generator) { + var n = 1; + var argument = generator.valueToCode(this, 'IF' + n, + generator.ORDER_NONE) || 'null'; + var branch = ''; + var t = generator.statementToCode(this, 'try') || ' pass\n'; + var code = 'try:\n' + t; + for (n = 1; n <= this.elseifCount_; n++) { + argument = generator.valueToCode(this, 'IF' + n, + generator.ORDER_NONE) || ''; + if (argument !== '') + argument = ' ' + argument + branch = generator.statementToCode(this, 'DO' + n) || ' pass\n'; + code += 'except' + argument + ': \n' + branch; + } + if (this.elseCount_) { + branch = generator.statementToCode(this, 'ELSE') || ' pass\n'; + code += 'finally:\n' + branch; + } + // code += '}'; + return code; +} + +// ok +export const controls_for = function (a, generator) { + var b = generator.variableDB_.getName(a.getFieldValue("VAR"), Blockly.Variables.NAME_TYPE), + //var b = generator.valueToCode(a, "VAR", generator.ORDER_MEMBER) || "''", + c = generator.valueToCode(a, "FROM", generator.ORDER_NONE) || "0", + d = generator.valueToCode(a, "TO", generator.ORDER_NONE) || "0", + e = generator.valueToCode(a, "STEP", generator.ORDER_NONE) || "1", + f = generator.statementToCode(a, "DO"), + f = generator.addLoopTrap(f, a.id) || generator.PASS, + g = "", + h = function (_, generator) { + return generator.provideFunction_("upRange", + ["def " + generator.FUNCTION_NAME_PLACEHOLDER_ + "(start, stop, step):", " while start <= stop:", " yield start", " start += abs(step)"]) + }, + k = function (_, generator) { + return generator.provideFunction_("downRange", ["def " + generator.FUNCTION_NAME_PLACEHOLDER_ + "(start, stop, step):", " while start >= stop:", " yield start", " start -= abs(step)"]) + } + a = function (a, b, c) { + return "(" + a + " <= " + b + ") and " + h() + "(" + a + ", " + b + ", " + c + ") or " + k() + "(" + a + ", " + b + ", " + c + ")" + } + if (Blockly.isNumber(c) && Blockly.isNumber(d) && + Blockly.isNumber(e)) + c = parseFloat(c), d = parseFloat(d), e = Math.abs(parseFloat(e)), 0 === c % 1 && 0 === d % 1 && 0 === e % 1 ? (c <= d ? (d++, a = 0 == c && 1 == e ? d : c + ", " + d, 1 != e && (a += ", " + e)) : (d--, a = c + ", " + d + ", -" + e), a = "range(" + a + ")") : (a = c < d ? h() : k(), a += "(" + c + ", " + d + ", " + e + ")"); + else { + var l = function (a, c) { + if (Blockly.isNumber(a)) + a = parseFloat(a); + else { + var d = generator.variableDB_.getDistinctName(b + c, Blockly.Variables.NAME_TYPE); + g += d + " = " + a + "\n"; + a = d + } + return a + }, + c = l(c, "_start"), + d = l(d, "_end"); + l(e, "_inc"); + a = "number" == typeof c && "number" == typeof d ? c < d ? h(c, d, e) : k(c, d, e) : a(c, d, e) + } + return g += "for " + b + " in " + a + ":\n" + f +} + +export const controls_for_range = function (block, generator) { + var iter = generator.variableDB_.getName(block.getFieldValue("VAR"), Blockly.Variables.NAME_TYPE), + from = generator.valueToCode(block, "FROM", generator.ORDER_NONE) || "0", + end = generator.valueToCode(block, "TO", generator.ORDER_NONE) || "0", + step = generator.valueToCode(block, "STEP", generator.ORDER_NONE) || "1", + dostatement = generator.statementToCode(block, "DO"), + pass = generator.addLoopTrap(dostatement, block.id) || generator.PASS; + generator.setups_["mixly_range"] = "def mixly_range(start, stop, step):\n" + + " for i in range(start, stop + 1, step):\n" + + " yield i\n\n"; + return "for " + iter + " in mixly_range(" + from + ", " + end + ", " + step + "):\n" + pass; +} + +export const controls_whileUntil = function (a, generator) { + var b = "UNTIL" == a.getFieldValue("MODE"), + c = generator.valueToCode(a, "BOOL", generator.ORDER_NONE) || "False", + d = generator.statementToCode(a, "DO"), + d = generator.addLoopTrap(d, a.id) || generator.PASS; + b && (c = "not " + c); + return "while " + c + ":\n" + d +} + +// export const controls_flow_statements = function (_, generator) { +// // Flow statements: continue, break. +// switch (this.getFieldValue('FLOW')) { +// case 'BREAK': +// return 'break;\n'; +// case 'CONTINUE': +// return 'continue;\n'; +// } +// throw 'Unknown flow statement.'; +// } + +//ok +export const controls_flow_statements = function (a) { + switch (a.getFieldValue("FLOW")) { + case "BREAK": + return "break\n"; + case "CONTINUE": + return "continue\n" + } + throw "Unknown flow statement."; +} + +// ok +export const controls_delay = function (_, generator) { + var delay_time = generator.valueToCode(this, 'DELAY_TIME', generator.ORDER_ATOMIC) || '1000' + var code = 'sleep(' + delay_time + ')\n'; + return code; +} + +// ok +export const Panic_with_status_code = function (_, generator) { + var status_code = generator.valueToCode(this, 'STATUS_CODE', generator.ORDER_ATOMIC) || '1000' + var code = 'panic(' + status_code + ')\n'; + return code; +} + +// ok +export const controls_millis = function (_, generator) { + generator.definitions_.import_time = "import time"; + var code = 'time.time()'; + return [code, generator.ORDER_ATOMIC]; +} + +// ok +export const reset = function (_, generator) { + generator.definitions_['import_microbit'] = 'from microbit import *' + return 'reset()\n'; +} +export const controls_interrupts = function () { + return 'interrupts();\n'; +} + +export const controls_nointerrupts = function () { + return 'noInterrupts();\n'; +} + + +export const controls_forEach = function (block, generator) { + // For each loop. + var variable0 = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '\'\''; + var argument0 = generator.valueToCode(block, 'LIST', + generator.ORDER_RELATIONAL) || '[]'; + var branch = generator.statementToCode(block, 'DO'); + branch = generator.addLoopTrap(branch, block.id) || + generator.PASS; + var code = 'for ' + variable0 + ' in ' + argument0 + ':\n' + branch; + return code; +} + +export const controls_range = function (_, generator) { + var from = generator.valueToCode(this, "FROM", generator.ORDER_NONE) || "0"; + var end = generator.valueToCode(this, "TO", generator.ORDER_NONE) || "0"; + var step = generator.valueToCode(this, "STEP", generator.ORDER_NONE) || "1"; + var code = "range(" + from + ", " + end + ", " + step + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const controls_lambda = function (a, generator) { + var c = generator.valueToCode(a, "BOOL", generator.ORDER_NONE) || "None", + d = generator.statementToCode(a, "DO") || "pass"; + var code = "lambda " + c + ": " + d; + code = code.replace('\n', '').replace(' ', '') + return [code, generator.ORDER_ATOMIC]; +} + +export const time_sleep = function (_, generator) { + generator.definitions_['import_time'] = 'import time'; + var delay_time = generator.valueToCode(this, 'DELAY_TIME', generator.ORDER_ATOMIC) || '1000' + var code = 'time.sleep(' + delay_time + ')\n'; + return code; +} + +export const controls_pass = function () { + return 'pass\n'; +} + +export const controls_thread = function (_, generator) { + generator.definitions_['import__thread'] = 'import _thread'; + var v = generator.valueToCode(this, "VAR", generator.ORDER_NONE) || "None"; + var callback = generator.variableDB_.getName( + generator.valueToCode(this, "callback", generator.ORDER_NONE) || "None", + Blockly.Procedures.NAME_TYPE + ); + var code = "_thread.start_new_thread(" + callback + ", " + v + ")\n"; + return code; +} + +// do-while循环 +export const do_while = function (_, generator) { + var value_select_data = generator.valueToCode(this, 'select_data', generator.ORDER_NONE) || "False"; + var statements_input_data = generator.statementToCode(this, 'input_data') + var dropdown_type = this.getFieldValue('type'); + if (dropdown_type == 'true') { + statements_input_data = statements_input_data + ' if (' + value_select_data + '):\n' + ' break\n'; + } + else { + statements_input_data = statements_input_data + ' if not (' + value_select_data + '):\n' + ' break\n'; + } + statements_input_data = generator.addLoopTrap(statements_input_data, this.id) || generator.PASS; + //var dropdown_type = this.getFieldValue('type'); + var code = 'while True:\n' + statements_input_data; + return code; +} + +// export const base_type = controls_type; +// export const controls_TypeLists = controls_typeLists; + +export const controls_repeat_ext = function (a, generator) { + var times = generator.valueToCode(this, 'TIMES', generator.ORDER_ATOMIC); + var d = generator.statementToCode(a, "DO"), + d = generator.addLoopTrap(d, a.id) || generator.PASS; + return 'for _my_variable in range(' + times + '):\n' + d; +} + + +export const garbage_collection = function (_, generator) { + generator.definitions_['import_gc'] = 'import gc'; + var code = 'gc.collect()\n' + return code; +} + +export const get_mem_alloc = function (_, generator) { + generator.definitions_['import_gc'] = 'import gc'; + var code = 'gc.mem_alloc()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const get_mem_free = function (_, generator) { + generator.definitions_['import_gc'] = 'import gc'; + var code = 'gc.mem_free()'; + return [code, generator.ORDER_ATOMIC] +} + +export const get_unique_identifier = function (_, generator) { + generator.definitions_['import_machine'] = 'import machine'; + var code = 'machine.unique_id()'; + return [code, generator.ORDER_ATOMIC]; +} + +// ok +export const controls_repeat = controls_repeat_ext; + +export const datetime_fromtimestamp = function(_,generator){ + generator.definitions_['import_datetime'] = 'import datetime'; + var ts = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = 'datetime.datetime.fromtimestamp(' + ts + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const gene_unique_identifier = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + generator.definitions_['import_' + version + 'uuid'] = 'from ' + version + ' import uuid'; + var code = 'uuid()'; + return [code, generator.ORDER_ATOMIC] +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/dicts.js b/mixly/boards/default_src/python/generators/dicts.js new file mode 100644 index 00000000..8fb44286 --- /dev/null +++ b/mixly/boards/default_src/python/generators/dicts.js @@ -0,0 +1,225 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for dictionary blocks. + * @author acbart@vt.edu (Austin Cory Bart) + */ +import * as Blockly from 'blockly/core'; +import { Boards } from 'mixly'; + +export const dicts_create_with = function (_, generator) { + // Create a list with any number of elements of any type. + //var dropdown_type = this.getFieldValue('TYPE'); + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + var keyName = this.getFieldValue('KEY' + n); + code[n] = keyName + ":" + (generator.valueToCode(this, 'ADD' + n, generator.ORDER_NONE) || default_value); + } + var code = varName + '= ' + '{' + code.join(', ') + '}\n'; + //var code =''+varName+'['+size+"]"+'='+ '{' + code.join(', ') + '}\n'; + //generator.setups_['setup_lists'+varName] = code; + return code; +} + +export const dicts_keys = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.keys()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_get = function (_, generator) { + var version = Boards.getSelectedBoardKey().split(':')[2] + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var text = generator.valueToCode(this, 'KEY', generator.ORDER_ASSIGNMENT); + // var text=this.getFieldValue('KEY'); + if (version=='educore'){ + var code = varName+'.get('+text+')'; + }else{ + var code = varName + "[" + text + "]"; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_get_default = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var text = generator.valueToCode(this, 'KEY', generator.ORDER_ASSIGNMENT); + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + // var text=this.getFieldValue('KEY'); + var code = varName + ".get(" + text + ',' + argument + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_add_or_change = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || 'mydict'; + var text = generator.valueToCode(this, 'KEY', generator.ORDER_ASSIGNMENT); + // var text=this.getFieldValue('KEY'); + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + "[" + text + "] = " + argument + '\n'; + return code; +} + +export const dicts_delete = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || 'mydict'; + var text = generator.valueToCode(this, 'KEY', generator.ORDER_ASSIGNMENT); + // var text=this.getFieldValue('KEY'); + var code = "del " + varName + "[" + text + "]\n"; + return code; +} + +export const dicts_update = function (_, generator) { + var varName2 = generator.valueToCode(this, 'DICT2', generator.ORDER_ASSIGNMENT) || '0'; + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.update(' + varName2 + ')\n'; + return code; +} + +export const dicts_clear = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.clear()\n'; + return code; +} + +export const dicts_items = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.items()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_values = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.values()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_length = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'len(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_deldict = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'del ' + varName + '\n'; + return code; +} + +export const dicts_add_change_del = function (block, generator) { + var dict = generator.valueToCode(block, 'DICT', + generator.ORDER_MEMBER) || '[]'; + var mode = block.getFieldValue('WHERE'); + var KEY = generator.valueToCode(this, 'KEY', generator.ORDER_ASSIGNMENT); + // var text=this.getFieldValue('KEY'); + + switch (mode) { + case 'INSERT': + //var at2 = block.getFieldValue('AT2'); + var at2 = generator.valueToCode(this, 'AT2', generator.ORDER_ASSIGNMENT) || '0'; + var code = dict + "[" + KEY + "] = " + at2 + '\n' + break; + case 'DELETE': + var code = 'del ' + dict + "[" + KEY + "]\n" + break; + default: + throw 'Unhandled option (lists_setIndex2)'; + } + return code; +} + +export const dicts_pop = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var text = generator.valueToCode(this, 'KEY', generator.ORDER_ASSIGNMENT); + // var text=this.getFieldValue('KEY'); + var code = varName + ".pop(" + text + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_setdefault = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || 'mydict'; + var text = generator.valueToCode(this, 'KEY', generator.ORDER_ASSIGNMENT); + // var text=this.getFieldValue('KEY'); + var argument = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + ".setdefault" + "(" + text + "," + argument + ")\n"; + return code; +} + +export const dicts_create_with_noreturn = function (_, generator) { + // Create a list with any number of elements of any type. + // var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + // Blockly.Variables.NAME_TYPE); + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var code = new Array(this.itemCount_); + var default_value = '0'; + + for (var n = 0; n < this.itemCount_; n++) { + var keyName = this.getFieldValue('KEY' + n); + code[n] = keyName + ": " + (generator.valueToCode(this, 'ADD' + n, generator.ORDER_NONE) || default_value); + } + // if (this.itemCount_!=1){ + // generator.definitions_['var_declare'+varName] = varName+'= '+ '(' + code.join(', ') + ')\n';} + // else { + // generator.definitions_['var_declare'+varName] = varName+'= '+ '(' + code.join(', ') + ',)\n';} + var code = '{' + code.join(', ') + '}'; + + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_todict = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0' + return ['dict(' + str + ')', generator.ORDER_ATOMIC]; +} + +export const dicts_to_json = function (_, generator) { + generator.definitions_['import_json'] = 'import json'; + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'json.dumps(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const json_to_dicts = function (_, generator) { + generator.definitions_['import_json'] = 'import json'; + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || 'null'; + var code = 'json.loads(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_to_to = function (_, generator) { + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var R = generator.valueToCode(this, 'VAR1', generator.ORDER_ASSIGNMENT) || 'null'; + var I = generator.valueToCode(this, 'VAR2', generator.ORDER_ASSIGNMENT) || 'null'; + var L = generator.valueToCode(this, 'VAR3', generator.ORDER_ASSIGNMENT) || 'null'; + var N = generator.valueToCode(this, 'VAR4', generator.ORDER_ASSIGNMENT) || 'null'; + var code = varName + '['+R+']'+'['+I+']'+'['+L+']'+'['+N+']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const dicts_to_json2 = function (_, generator) { + generator.definitions_['import_json'] = 'import json'; + generator.definitions_['import_ujson'] = 'import ujson'; + var varName = generator.valueToCode(this, 'DICT', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'ujson.loads(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/html.js b/mixly/boards/default_src/python/generators/html.js new file mode 100644 index 00000000..3b1b6d3c --- /dev/null +++ b/mixly/boards/default_src/python/generators/html.js @@ -0,0 +1,70 @@ +export const html_document = function (_, generator) { + var head = generator.statementToCode(this, 'HEAD'); + var body = generator.statementToCode(this, 'BODY'); + var code = "'''\n\n\n" + '\t\n' + head + "\n\n" + body + "\n\n'''"; + return [code, generator.ORDER_ATOMIC]; +} + +export const html_title = function (_, generator) { + var t = generator.statementToCode(this, 'DO'); + var l = this.getFieldValue('LEVEL'); + var code = "\n" + t + "\n"; + return code; +} + +export const html_head_body = function (_, generator) { + var t = generator.statementToCode(this, 'DO'); + var l = this.getFieldValue('LEVEL'); + if (l == 'head') { + var code = "<" + l + '>\n\t\n' + t + "\n"; + } + else { + var code = "<" + l + ">\n" + t + "\n"; + } + return code; +} + +export const html_content = function (_, generator) { + var t = generator.statementToCode(this, 'DO'); + // var s = generator.valueToCode(this, 'style'); + var l = this.getFieldValue('LEVEL'); + // var code = "<" + l + " " + s + " >\n" + t + "\n"; + var code = "<" + l + ">\n" + t + "\n"; + return code; +} + +export const html_content_more = function (_, generator) { + var t = generator.statementToCode(this, 'DO'); + var s = generator.valueToCode(this, 'style'); + var l = this.getFieldValue('LEVEL'); + var code = "<" + l + " " + s + " >\n" + t + "\n"; + return code; +} + +export const html_style = function (_, generator) { + var style = generator.statementToCode(this, 'STYLE'); + var code = 'style="' + style + '"'; + return [code, generator.ORDER_ATOMIC]; +} + +export const html_form = function (_, generator) { + var tag = this.getFieldValue('LEVEL'); + var name = this.getFieldValue('NAME'); + var value = this.getFieldValue('VALUE'); + var s = generator.valueToCode(this, 'style') || ""; + var code = ''; + return code; +} + +export const html_style_content = function () { + var key = this.getFieldValue('KEY'); + var value = this.getFieldValue('VALUE'); + var code = key + ':' + value + ";"; + return code; +} + +export const html_text = function () { + var text = this.getFieldValue('TEXT'); + var code = text + "\n"; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/lists.js b/mixly/boards/default_src/python/generators/lists.js new file mode 100644 index 00000000..b70ca796 --- /dev/null +++ b/mixly/boards/default_src/python/generators/lists.js @@ -0,0 +1,270 @@ +import * as Blockly from 'blockly/core'; + +export const lists_get_sublist = function (_, generator) { + // Get sublist. + var list = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var at1 = generator.valueToCode(this, 'AT1', generator.ORDER_ADDITIVE); + var at2 = generator.valueToCode(this, 'AT2', generator.ORDER_ADDITIVE); + var code = list + '[' + at1 + ' : ' + at2 + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_2d_get_data_with_col_row = function (_, generator) { + var value_LIST = generator.valueToCode(this, 'LIST', generator.ORDER_ATOMIC) || 'mylist'; + var value_row = generator.valueToCode(this, 'row', generator.ORDER_ATOMIC) || 0; + var value_col = generator.valueToCode(this, 'col', generator.ORDER_ATOMIC) || 0; + var code = value_LIST + '[' + value_row + ',' + value_col + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_2d_get_col_row_data = function (_, generator) { + var value_LIST = generator.valueToCode(this, 'LIST', generator.ORDER_ATOMIC) || 'mylist'; + var value_row_start = generator.valueToCode(this, 'row_start', generator.ORDER_ATOMIC) || 0; + var value_row_end = generator.valueToCode(this, 'row_end', generator.ORDER_ATOMIC) || 1; + var value_col_start = generator.valueToCode(this, 'col_start', generator.ORDER_ATOMIC) || 0; + var value_col_end = generator.valueToCode(this, 'col_end', generator.ORDER_ATOMIC) || 1; + var code = value_LIST + '[' + value_row_start + ' : ' + value_row_end + ',' + value_col_start + ' : ' + value_col_end + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_create_with = function (_, generator) { + // Create a list with any number of elements of any type. + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + //generator.setups_['var_declare'+varName] = varName+' = '+ '[' + code.join(', ') + ']\n'; + var code = varName + ' = ' + '[' + code.join(', ') + ']\n'; + return code; +} + +export const lists_create_with_text = function (_, generator) { + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var text = this.getFieldValue('TEXT'); + // generator.setups_['var_declare'+varName] = varName+' = '+ '[' + text + ']\n'; + var code = varName + ' = ' + '[' + text + ']\n'; + return code; +} + +export const lists_get_index = function (_, generator) { + // Indexing into a list is the same as indexing into a string. + var list = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var argument0 = generator.valueToCode(this, 'AT', generator.ORDER_ADDITIVE) || 0; + var code = list + '[' + argument0 + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_set_index = function (_, generator) { + // Set element at index. + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var argument0 = generator.valueToCode(this, 'AT', + generator.ORDER_ADDITIVE) || '0'; + var argument2 = generator.valueToCode(this, 'TO', + generator.ORDER_ASSIGNMENT) || '0'; + // Blockly uses one-based indicies. + return varName + '[' + argument0 + '] = ' + argument2 + '\n'; +} + +export const lists_append_extend = function (_, generator) { + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT) || '0'; + var argument = generator.valueToCode(this, 'DATA', generator.ORDER_ASSIGNMENT) || '0'; + var op = this.getFieldValue('OP'); + var code = varName + '.' + op + '(' + argument + ')\n'; + return code; +} + +export const lists_get_random_item = function (_, generator) { + generator.definitions_['import_random'] = 'import random'; + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var code = 'random.choice(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_get_random_sublist = function (_, generator) { + generator.definitions_['import_random'] = 'import random'; + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var VALUE = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'random.sample(' + varName + ',' + VALUE + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_insert_value = function (_, generator) { + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT) || '0'; + var at = generator.valueToCode(this, 'AT', generator.ORDER_ADDITIVE) || '0'; + var VALUE = generator.valueToCode(this, 'VALUE', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.insert(' + at + ', ' + VALUE + ')\n'; + return code; +} + +export const lists_reverse = function (_, generator) { + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.reverse()\n'; + return code; +} +export const lists_clear = function (_, generator) { + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.clear()\n'; + return code; +} + +export const lists_find = function (_, generator) { + var op = this.getFieldValue('OP'); + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var argument = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT) || '0'; + if (op == 'INDEX') + var code = varName + '.index(' + argument + ')'; + else if (op == 'COUNT') + var code = varName + '.count(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_remove_at = function (_, generator) { + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT) || '0'; + var argument = generator.valueToCode(this, 'DATA', generator.ORDER_ASSIGNMENT) || '0'; + var op = this.getFieldValue('OP'); + var code = ""; + if (op == "del") { + code = 'del ' + varName + '[' + argument + ']\n'; + } else { + code = varName + '.remove' + '(' + argument + ')\n'; + } + return code; +} + +export const lists_pop = function (_, generator) { + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var argument = generator.valueToCode(this, 'VALUE', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.pop(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const list_trig = function (a, generator) { + var b = a.getFieldValue("OP"), c; + generator.definitions_['import_math'] = "import math"; + a = generator.valueToCode(a, 'data', generator.ORDER_NONE) + switch (b) { + case "LEN": + c = "len(" + a + ")"; + break; + case "SUM": + c = "sum(" + a + ")"; + break; + case "MIN": + c = "min(" + a + ")"; + break; + case "MAX": + c = "max(" + a + ")"; + break; + case 'AVERAGE': + generator.definitions_['import_mixpy_math_mean'] = "from mixpy import math_mean"; + c = 'math_mean(' + a + ')'; + break; + case 'MEDIAN': + generator.definitions_['import_mixpy_math_median'] = "from mixpy import math_median"; + c = 'math_median(' + a + ')'; + break; + case 'MODE': + generator.definitions_['import_mixpy_math_modes'] = "from mixpy import math_modes"; + c = 'math_modes(' + a + ')'; + break; + case 'STD_DEV': + generator.definitions_['import_mixpy_math_standard_deviation'] = "from mixpy import math_standard_deviation"; + c = 'math_standard_deviation(' + a + ')'; + break; + default: + throw 'Unknown operator: ' + b; + } + if (c) + return [c, generator.ORDER_ATOMIC]; + +} + +export const lists_sort = function (block, generator) { + // Block for sorting a list. + generator.definitions_['import_mixpy_lists_sort'] = "from mixpy import lists_sort"; + var list = (generator.valueToCode(block, 'LIST', + generator.ORDER_NONE) || '[]'); + var type = block.getFieldValue('TYPE'); + var reverse = block.getFieldValue('DIRECTION') === '1' ? 'False' : 'True'; + var code = 'lists_sort(' + list + ', "' + type + '", ' + reverse + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_change_to = function (_, generator) { + var op = this.getFieldValue('OP'); + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = ''; + if (op == 'array') { + generator.definitions_['import_numpy'] = 'import numpy'; + code = 'numpy.array(' + varName + ')'; + } + else { + code = op + '(' + varName + ')'; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const list_many_input = function (_, generator) { + var text = this.getFieldValue('CONTENT'); + var code = '[' + text + ']' + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_create_with_noreturn = function (_, generator) { + // Create a list with any number of elements of any type. + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + var code = '[' + code.join(', ') + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const lists_change_to_general = lists_change_to; + +export const lists_del_general = function (_, generator) { + var varName = generator.valueToCode(this, 'TUP', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'del ' + varName + '\n'; + return code; +} + +export const lists_create_with2 = lists_create_with +export const lists_create_with_text2 = lists_create_with_text +export const lists_getIndex3 = lists_get_index +export const lists_getSublist3 = lists_get_sublist +export const lists_setIndex3 = lists_set_index +export const lists_insert_value2 = lists_insert_value +export const lists_remove_at2 = lists_remove_at + +export const list_tolist = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0' + return ['list(' + str + ')', generator.ORDER_ATOMIC]; +} + +export const list_tolist2 = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0' + return [str + '.tolist()', generator.ORDER_ATOMIC]; +} + +export const enumerate = function (_, generator) { + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var argument = generator.valueToCode(this, 'VALUE', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'enumerate(' +varName+',start='+ argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const content_in_lists = function (_, generator) { + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || 'mylist'; + var con = generator.valueToCode(this, 'CON', generator.ORDER_ASSIGNMENT) || '0'; + var code = con +' in '+varName; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/logic.js b/mixly/boards/default_src/python/generators/logic.js new file mode 100644 index 00000000..8e4055fe --- /dev/null +++ b/mixly/boards/default_src/python/generators/logic.js @@ -0,0 +1,102 @@ +export const logic_compare = function (_, generator) { + // Comparison operator. + var mode = this.getFieldValue('OP'); + var operator = logic_compare.OPERATORS[mode]; + var order = (operator == '==' || operator == '!=') ? + generator.ORDER_EQUALITY : generator.ORDER_RELATIONAL; + var argument0 = generator.valueToCode(this, 'A', order) || '0'; + var argument1 = generator.valueToCode(this, 'B', order) || '0'; + var code = argument0 + ' ' + operator + ' ' + argument1; + return [code, order]; +} + +export const logic_compare_continous = function (_, generator) { + // Comparison operator. + var mode1 = this.getFieldValue('OP1'); + var operator1 = logic_compare.OPERATORS[mode1]; + var mode2 = this.getFieldValue('OP2'); + var operator2 = logic_compare.OPERATORS[mode2]; + var argument0 = generator.valueToCode(this, 'A', generator.ORDER_RELATIONAL) || '0'; + var argument1 = generator.valueToCode(this, 'B', generator.ORDER_RELATIONAL) || '0'; + var argument2 = generator.valueToCode(this, 'C', generator.ORDER_RELATIONAL) || '0'; + var code = argument0 + ' ' + operator1 + ' ' + argument1 + ' ' + operator2 + ' ' + argument2; + return [code, generator.ORDER_RELATIONAL]; +} + +logic_compare.OPERATORS = { + EQ: '==', + NEQ: '!=', + LT: '<', + LTE: '<=', + GT: '>', + GTE: '>=' +}; + +export const logic_operation = function (_, generator) { + // Operations 'and', 'or'. + var operator = this.getFieldValue('OP'); + var order = (operator == '&&') ? generator.ORDER_LOGICAL_AND : + generator.ORDER_LOGICAL_OR; + var argument0 = generator.valueToCode(this, 'A', order) || 'False'; + var argument1 = generator.valueToCode(this, 'B', order) || 'False'; + if (operator == 'AND') { + var code = argument0 + ' and ' + argument1; + } else if (operator == 'OR') { + var code = argument0 + ' or ' + argument1; + } else if (operator == 'NOR') { + // var code = '('+argument0+' and '+argument1+' ) or ((not '+argument0+') and (not '+argument1+'))'; + var code = 'not(' + argument0 + '^' + argument1 + ')'; + } else { + // var code = '((not '+argument0+') and '+argument1+' ) or ( '+argument0+' and (not '+argument1+'))'; + var code = argument0 + '^' + argument1; + } + return [code, order]; +} + +export const logic_negate = function (_, generator) { + // Negation. + var order = generator.ORDER_UNARY_PREFIX; + var argument0 = generator.valueToCode(this, 'BOOL', order) || 'False'; + var code = 'not ' + argument0; + return [code, order]; +} + +export const logic_boolean = function (_, generator) { + // Boolean values true and false. + var code = (this.getFieldValue('BOOL') == 'TRUE') ? 'True' : 'False'; + return [code, generator.ORDER_ATOMIC]; +} + +export const logic_null = function (_, generator) { + var code = 'None'; + return [code, generator.ORDER_ATOMIC]; +} + +export const logic_true_or_false = function (_, generator) { + var a = generator.valueToCode(this, 'A', generator.ORDER_ATOMIC) || 'False'; + var b = generator.valueToCode(this, 'B', generator.ORDER_ATOMIC) || 'False'; + var c = generator.valueToCode(this, 'C', generator.ORDER_ATOMIC) || 'False'; + var code = '(' + b + ' if ' + a + ' else ' + c + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const logic_is_in = function (_, generator) { + var a = generator.valueToCode(this, 'A', generator.ORDER_ATOMIC) || '\'\''; + var b = generator.valueToCode(this, 'B', generator.ORDER_ATOMIC) || '\'\''; + var bool = this.getFieldValue('BOOL'); + var code = a + ' ' + bool + ' ' + b; + return [code, generator.ORDER_ATOMIC]; +} + +export const logic_is = function (_, generator) { + var a = generator.valueToCode(this, 'A', generator.ORDER_ATOMIC) || '\'\''; + var b = generator.valueToCode(this, 'B', generator.ORDER_ATOMIC) || '\'\''; + var bool = this.getFieldValue('BOOL'); + var code = a + ' ' + bool + ' ' + b; + return [code, generator.ORDER_ATOMIC]; +} + +export const logic_tobool = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0' + return ['bool(' + str + ')', generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/math.js b/mixly/boards/default_src/python/generators/math.js new file mode 100644 index 00000000..643f7c95 --- /dev/null +++ b/mixly/boards/default_src/python/generators/math.js @@ -0,0 +1,338 @@ +// export const math_number = function() { +// // Numeric value. +// var code = (this.getFieldValue('NUM')); +// // -4.abs() returns -4 in Dart due to strange order of operation choices. +// // -4 is actually an operator and a number. Reflect this in the order. +// var order = code < 0 ? +// generator.ORDER_UNARY_PREFIX : generator.ORDER_ATOMIC; +// return [code, order]; +// } + +// generator.math = {} +// generator.addReservedWords("math,random,Number"); + +export const math_number = function (_, generator) { + // a = parseFloat(a.getFieldValue("NUM")); + // var b; + // Infinity == a ? (a = 'float("inf")', b = generator.ORDER_FUNCTION_CALL) : -Infinity == a ? (a = '-float("inf")', b = generator.ORDER_UNARY_SIGN) : b = 0 > a ? generator.ORDER_UNARY_SIGN : generator.ORDER_ATOMIC; + // return [a, b] + + var code = this.getFieldValue('NUM'); + // -4.abs() returns -4 in Dart due to strange order of operation choices. + // -4 is actually an operator and a number. Reflect this in the order. + var order = code < 0 ? + generator.ORDER_UNARY_PREFIX : generator.ORDER_ATOMIC; + return [code, order]; +} + +export const math_constant = function (_, generator) { + generator.definitions_.import_math = "import math"; + var name = this.getFieldValue('CONSTANT'); + var code = 'math.' + name; + return [code, generator.ORDER_ATOMIC]; +} + +export const math_constant_mp = function (_, generator) { + generator.definitions_.import_math = "import math"; + var name = this.getFieldValue('CONSTANT'); + var code = 'math.' + name; + return [code, generator.ORDER_ATOMIC]; +} + +export const math_bit = function (_, generator) { + var operator = this.getFieldValue('OP'); + var order = generator.ORDER_ATOMIC; + var argument0 = generator.valueToCode(this, 'A', order) || '0'; + var argument1 = generator.valueToCode(this, 'B', order) || '0'; + var code = '(' + argument0 + operator + argument1 + ')'; + return [code, order]; +} + +export const math_arithmetic = function (a, generator) { + var b = { + ADD: [" + ", generator.ORDER_ADDITIVE], + MINUS: [" - ", generator.ORDER_ADDITIVE], + MULTIPLY: [" * ", generator.ORDER_MULTIPLICATIVE], + DIVIDE: [" / ", generator.ORDER_MULTIPLICATIVE], + QUYU: [' % ', generator.ORDER_MULTIPLICATIVE],//增加取余操作 + ZHENGCHU: [' // ', generator.ORDER_MULTIPLICATIVE],//增加整除操作 + POWER: [" ** ", generator.ORDER_EXPONENTIATION] + }[a.getFieldValue("OP")]; + var c = b[0], + b = b[1], + d = generator.valueToCode(a, "A", b) || "0"; + a = generator.valueToCode(a, "B", b) || "0"; + return [d + c + a, b] +} + +export const math_selfcalcu = function (_, generator) { + var argument0 = generator.valueToCode(this, 'A', generator.ORDER_RELATIONAL) || '0'; + var argument1 = generator.valueToCode(this, 'B', generator.ORDER_RELATIONAL) || '0'; + var operator = this.getFieldValue('OP'); + switch (operator) { + case 'ADD': var op = '+='; break; + case 'MINUS': var op = '-='; break; + case 'MULTIPLY': var op = '*='; break; + case 'DIVIDE': var op = '/='; break; + case 'QUYU': var op = '%='; break; + case 'ZHENGCHU': var op = '//='; break; + case 'POWER': var op = '**='; break; + } + var code = argument0 + ' ' + op + ' ' + argument1 + '\n'; + return code; +} + +export const math_single = function (a, generator) { + var b = a.getFieldValue("OP"), + c; + if ("NEG" == b) + return c = generator.valueToCode(a, "NUM", generator.ORDER_UNARY_SIGN) || "0", ["-" + c, generator.ORDER_UNARY_SIGN]; + generator.definitions_['import_math'] = "import math"; + a = "SIN" == b || "COS" == b || "TAN" == b ? generator.valueToCode(a, "NUM", generator.ORDER_MULTIPLICATIVE) || "0" : generator.valueToCode(a, "NUM", generator.ORDER_NONE) || "0"; + switch (b) { + case "ABS": + c = "math.fabs(" + a + ")"; + break; + case "ROOT": + c = "math.sqrt(" + + a + ")"; + break; + case "LN": + c = "math.log(" + a + ")"; + break; + case "LOG10": + c = "math.log10(" + a + ")"; + break; + case "EXP": + c = "math.exp(" + a + ")"; + break; + case "POW10": + c = "math.pow(10," + a + ")"; + break; + case "ROUND": + c = "round(" + a + ")"; + break; + case "ROUNDUP": + c = "math.ceil(" + a + ")"; + break; + case "ROUNDDOWN": + c = "math.floor(" + a + ")"; + break; + case "SIN": + c = "math.sin(" + a + ")"; + break; + case "COS": + c = "math.cos(" + a + ")"; + break; + case "TAN": + c = "math.tan(" + a + ")"; + break; + case "++": + c = "++(" + a + ")"; + break; + case "--": + c = "--(" + a + ")"; + break; + case "-": + c = "-(" + a + ")"; + break; + default: + } + if (c) + return [c, generator.ORDER_EXPONENTIATION]; + switch (b) { + case "ASIN": + c = "math.degrees(math.asin(" + a + "))"; + break; + case "ACOS": + c = "math.degrees(math.acos(" + a + "))"; + break; + case "ATAN": + c = "math.degrees(math.atan(" + a + "))"; + break; + } + return [c, generator.ORDER_MULTIPLICATIVE] +} + +export const math_trig = math_single; + +export const math_dec = function (_, generator) { + var argument0 = generator.valueToCode(this, 'NUM', generator.ORDER_NONE) || '0'; + var operator = this.getFieldValue('OP'); + var code = operator + '(' + argument0 + ')'; + return [code, generator.ORDER_ATOMIC]; + +} + +export const math_to_int = function (_, generator) { + var argument0 = generator.valueToCode(this, 'A', generator.ORDER_NONE) || '0'; + var operator = this.getFieldValue('OP'); + var code = ""; + if (operator === "round") { + code = operator + '(' + argument0 + ')'; + } else { + code = "math." + operator + '(' + argument0 + ')'; + generator.definitions_.import_math = "import math"; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const math_max_min = function (_, generator) { + var a = generator.valueToCode(this, 'A', generator.ORDER_NONE) || '0'; + var b = generator.valueToCode(this, 'B', generator.ORDER_NONE) || '0'; + var operator = this.getFieldValue('OP'); + var code = operator + '(' + a + ', ' + b + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const math_random = function (_, generator) { + generator.definitions_.import_random = "import random"; + // Random integer between [X] and [Y]. + var type = this.getFieldValue('TYPE'); + var argument0 = generator.valueToCode(this, 'FROM', + generator.ORDER_NONE) || '0'; + var argument1 = generator.valueToCode(this, 'TO', + generator.ORDER_NONE) || '0'; + if (type == 'int') { + var code = 'random.randint(' + argument0 + ', ' + argument1 + ')'; + } else if (type == 'float') { + var code = 'random.uniform(' + argument0 + ', ' + argument1 + ')'; + } + return [code, generator.ORDER_UNARY_POSTFIX]; +} + +export const math_map = function (_, generator) { + var value_num = generator.valueToCode(this, 'NUM', generator.ORDER_NONE); + var value_fl = generator.valueToCode(this, 'fromLow', generator.ORDER_ATOMIC); + var value_fh = generator.valueToCode(this, 'fromHigh', generator.ORDER_ATOMIC); + var value_tl = generator.valueToCode(this, 'toLow', generator.ORDER_ATOMIC); + var value_th = generator.valueToCode(this, 'toHigh', generator.ORDER_ATOMIC); + generator.definitions_['import_mixpy_math_map'] = "from mixpy import math_map"; + var code = 'math_map(' + value_num + ', ' + value_fl + ', ' + value_fh + ', ' + value_tl + ', ' + value_th + ')'; + return [code, generator.ORDER_NONE]; +} + +export const math_constrain = function (_, generator) { + // Constrain a number between two limits. + var argument0 = generator.valueToCode(this, 'VALUE', + generator.ORDER_NONE) || '0'; + var argument1 = generator.valueToCode(this, 'LOW', + generator.ORDER_NONE) || '0'; + var argument2 = generator.valueToCode(this, 'HIGH', + generator.ORDER_NONE) || '0'; + var code = 'min(max(' + argument0 + ', ' + argument1 + '), ' + argument2 + ')'; + return [code, generator.ORDER_UNARY_POSTFIX]; +} + +export const math_number_base_conversion = function (a, generator) { + var c1 = a.getFieldValue("OP"); + var d = generator.valueToCode(this, 'NUM', generator.ORDER_NONE) || '0'; + var c2 = a.getFieldValue("OP2"); + generator.definitions_['import_math'] = "import math"; + var param1 = ""; + var param2 = "10"; + if (c1 == "two") { + param2 = '2'; + } else if (c1 == "eight") { + param2 = '8' + } else if (c1 == "ten") { + param2 = '10' + } else if (c1 == "sixteen") { + param2 = '16' + } + + if (c2 == "two") { + param1 = 'bin'; + } else if (c2 == "eight") { + param1 = 'oct' + } else if (c2 == "ten") { + param1 = '' + } else if (c2 == "sixteen") { + param1 = 'hex' + } + if (param1 == "") { + var code = "int(str(" + d + "), " + param2 + ")"; + } else { + var code = param1 + "(int(str(" + d + "), " + param2 + "))"; + + } + return [code, generator.ORDER_ATOMIC]; +} + +export const math_random_seed = function (_, generator) { + // Random integer between [X] and [Y]. + generator.definitions_.import_random = "import random"; + var a = generator.valueToCode(this, 'NUM', generator.ORDER_NONE) || '0'; + var code = 'random.seed(' + a + ');' + '\n'; + return code; +} + +export const math_indexer_number = function (_, generator) { + var code = this.getFieldValue('NUM'); + // -4.abs() returns -4 in Dart due to strange order of operation choices. + // -4 is actually an operator and a number. Reflect this in the order. + var order = code < 0 ? + generator.ORDER_UNARY_PREFIX : generator.ORDER_ATOMIC; + return [code, order]; +} + +export const math_round = function (_, generator) { + var argument0 = generator.valueToCode(this, 'VALUE', + generator.ORDER_NONE) || '0'; + var argument1 = generator.valueToCode(this, 'VAR', + generator.ORDER_NONE) || '0'; + + var code = 'round(' + argument0 + ', ' + argument1 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_to_number = function (_, generator) { + var towhat = this.getFieldValue('TOWHAT'); + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (towhat == 'b') return ['' + str + '.encode("utf-8")', generator.ORDER_ATOMIC]; + else if (towhat == 'bti') return ['int.from_bytes(' + str + ',"big")', generator.ORDER_ATOMIC]; + return [towhat + "(" + str + ')', generator.ORDER_ATOMIC]; +} + +export const text_to_number_skulpt = function (_, generator) { + var towhat = this.getFieldValue('TOWHAT'); + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + if (towhat == 'b') return ['' + str + '.encode("utf-8")', generator.ORDER_ATOMIC]; + return [towhat + "(" + str + ')', generator.ORDER_ATOMIC]; +} + +export const base_map = math_map; + +export const turn_to_int = function (_, generator) { + generator.definitions_.import_hexlify = "from ubinascii import hexlify"; + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return ["hexlify(" + str + ').decode()', generator.ORDER_ATOMIC]; +} + +export const generate_cartesian_product = function (_, generator) { + generator.definitions_.import_itertools = 'import itertools'; + let re = generator.valueToCode(this, 'REPEAT', generator.ORDER_ATOMIC); + let items = new Array(this.itemCount_); + for (let n = 0; n < this.itemCount_; n++) { + items[n] = generator.valueToCode(this, `ADD${n}`, generator.ORDER_NONE) || '0'; + } + let code = ''; + if (this.itemCount_) { + code = `itertools.product(${items.join(', ')}, repeat=${re})`; + } + return [code, generator.ORDER_ATOMIC]; +} + +export const math_radian_to_degree = function (_, generator) { + generator.definitions_.import_math = "import math"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = 'math.degrees('+ v + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const math_degree_to_radian = function (_, generator) { + generator.definitions_.import_math = "import math"; + var v = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = 'math.radians('+ v + ')'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/procedures.js b/mixly/boards/default_src/python/generators/procedures.js new file mode 100644 index 00000000..c7c2d326 --- /dev/null +++ b/mixly/boards/default_src/python/generators/procedures.js @@ -0,0 +1,107 @@ +import * as Blockly from 'blockly/core'; + +export const procedures_defreturn = function (_, generator) { + // Define a procedure with a return value. + var funcName = generator.variableDB_.getName(this.getFieldValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var branch = (this.getInput('STACK') && generator.statementToCode(this, 'STACK')) ?? ' pass\n'; + if (generator.INFINITE_LOOP_TRAP) { + branch = generator.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + this.id + '\'') + branch; + } + var returnValue = generator.valueToCode(this, 'RETURN', + generator.ORDER_NONE) || ''; + //var type=this.getFieldValue('TYPE'); + if (returnValue) { + returnValue = ' return ' + returnValue + '\n'; + } + //var returnType = returnValue ? type : 'void'; + var args = []; + for (var x = 0; x < this.arguments_.length; x++) { + var varName = generator.variableDB_.getName(this.arguments_[x], Blockly.Variables.NAME_TYPE); + args[x] = varName; + } + var code = 'def ' + funcName + '(' + args.join(', ') + '):\n' + + branch + returnValue + '\n'; + code = generator.scrub_(this, code); + generator.setups_[funcName] = code; + return null; +} + +export const procedures_defnoreturn = function (_, generator) { + // Define a procedure with a return value. + var funcName = generator.variableDB_.getName(this.getFieldValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var branch = (this.getInput('STACK') && generator.statementToCode(this, 'STACK')) ?? ' pass\n'; + if (generator.INFINITE_LOOP_TRAP) { + branch = generator.INFINITE_LOOP_TRAP.replace(/%1/g, + '\'' + this.id + '\'') + branch; + } + //var returnType = returnValue ? type : 'void'; + var args = []; + for (var x = 0; x < this.arguments_.length; x++) { + var varName = generator.variableDB_.getName(this.arguments_[x], Blockly.Variables.NAME_TYPE); + args[x] = varName; + } + var code = 'def ' + funcName + '(' + args.join(', ') + '):\n' + + branch + '\n'; + code = generator.scrub_(this, code); + generator.setups_[funcName] = code; + return null; +} + +export const procedures_callreturn = function (_, generator) { + // Call a procedure with a return value. + var funcName = generator.variableDB_.getName(this.getFieldValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var args = []; + for (var x = 0; x < this.arguments_.length; x++) { + args[x] = generator.valueToCode(this, 'ARG' + x, + generator.ORDER_NONE) || 'null'; + } + var code = funcName + '(' + args.join(', ') + ')'; + return [code, generator.ORDER_UNARY_POSTFIX]; +} + +export const procedures_callnoreturn = function (_, generator) { + // Call a procedure with no return value. + var funcName = generator.variableDB_.getName(this.getFieldValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var args = []; + for (var x = 0; x < this.arguments_.length; x++) { + args[x] = generator.valueToCode(this, 'ARG' + x, + generator.ORDER_NONE) || 'null'; + } + var code = funcName + '(' + args.join(', ') + ')\n'; + return code; +} + +export const procedures_ifreturn = function (_, generator) { + // Conditionally return value from a procedure. + var condition = generator.valueToCode(this, 'CONDITION', + generator.ORDER_NONE) || 'False'; + var code = 'if (' + condition + ') :\n'; + if (this.hasReturnValue_) { + var value = generator.valueToCode(this, 'VALUE', + generator.ORDER_NONE) || 'None'; + code += ' return ' + value; + } else { + code += ' return None'; + } + code += '\n'; + return code; +} + +export const procedures_return = function (_, generator) { + // Conditionally return value from a procedure. + var code = "" + if (this.hasReturnValue_) { + var value = generator.valueToCode(this, 'VALUE', + generator.ORDER_NONE) || 'None'; + code += 'return ' + value; + } else { + code += 'return None'; + } + code += '\n'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/set.js b/mixly/boards/default_src/python/generators/set.js new file mode 100644 index 00000000..7b9f0464 --- /dev/null +++ b/mixly/boards/default_src/python/generators/set.js @@ -0,0 +1,95 @@ +import * as Blockly from 'blockly/core'; + +export const set_create_with = function (_, generator) { + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + //generator.definitions_['var_declare'+varName] = varName+'= '+ '{' + code.join(', ') + '}\n'; + code = varName + '= ' + '{' + code.join(', ') + '}\n'; + if (this.itemCount_ == 0) { code = varName + ' = ' + 'set()\n' } + return code; +} + +export const set_length = function (_, generator) { + var varName = generator.valueToCode(this, 'SET', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'len(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const set_pop = function (_, generator) { + var varName = generator.valueToCode(this, 'SET', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.pop()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const set_clear = function (_, generator) { + var varName = generator.valueToCode(this, 'SET', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + '.clear()\n'; + return code; +} + +export const set_operate = function (_, generator) { + var vars1 = generator.valueToCode(this, 'SET1', generator.ORDER_ASSIGNMENT) || '0'; + var vars2 = generator.valueToCode(this, 'SET2', generator.ORDER_ASSIGNMENT) || '0'; + var operate = this.getFieldValue('OPERATE'); + //var num = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = vars1 + "." + operate + "(" + vars2 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const set_operate_update = function (_, generator) { + var vars1 = generator.valueToCode(this, 'SET1', generator.ORDER_ASSIGNMENT) || '0'; + var vars2 = generator.valueToCode(this, 'SET2', generator.ORDER_ASSIGNMENT) || '0'; + var operate = this.getFieldValue('OPERATE'); + //var num = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = vars1 + "." + operate + "(" + vars2 + ')\n'; + return code; +} + +export const set_add_discard = function (_, generator) { + var vars1 = generator.valueToCode(this, 'SET', generator.ORDER_ASSIGNMENT) || '0'; + var operate = this.getFieldValue('OPERATE'); + var argument = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT) || '0'; + var code = vars1 + "." + operate + "(" + argument + ')\n'; + return code; +} + +export const set_sub = function (_, generator) { + var vars1 = generator.valueToCode(this, 'SET1', generator.ORDER_ASSIGNMENT) || '0'; + var vars2 = generator.valueToCode(this, 'SET2', generator.ORDER_ASSIGNMENT) || '0'; + var operate = this.getFieldValue('OPERATE'); + //var num = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = vars1 + "." + operate + "(" + vars2 + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const set_update = function (_, generator) { + var varName = generator.valueToCode(this, 'SET', generator.ORDER_ASSIGNMENT) || '0'; + var color = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + //var color = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName + "." + 'update' + '(' + color + ')\n'; + return code; +} + +// export const set_change_to = function(){ +// var op = this.getFieldValue('OP'); +// var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; +// var code = op + '(' + varName + ')\n'; +// return [code, generator.ORDER_ATOMIC]; +// } + +export const set_create_with_text_return = function (_, generator) { + var text = this.getFieldValue('TEXT'); + var code = '{' + text + '}'; + return [code, generator.ORDER_ATOMIC]; +} + +export const set_toset = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0' + return ['set(' + str + ')', generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/storage.js b/mixly/boards/default_src/python/generators/storage.js new file mode 100644 index 00000000..f04d9cb4 --- /dev/null +++ b/mixly/boards/default_src/python/generators/storage.js @@ -0,0 +1,175 @@ +export const storage_open_file_with_os = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var fn = generator.valueToCode(this, 'fn', generator.ORDER_ATOMIC); + return "os.startfile(" + fn + ")\n"; +} + +export const storage_fileopen = function (_, generator) { + // For each loop. + var variable0 = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var fn = generator.valueToCode(this, 'FILENAME', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('MODE'); + var code = variable0 + ' = open(' + fn + ', \'' + mode + '\')\n'; + return code; +} + +export const storage_fileopen_new = function (_, generator) { // For each loop. + var fn = generator.valueToCode(this, 'FILENAME', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('MODE'); + var code = 'open(' + fn + ', \'' + mode + '\')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_fileopen_new_encoding = function (_, generator) { // For each loop. + var fn = generator.valueToCode(this, 'FILENAME', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('MODE'); + var encode = this.getFieldValue('CODE'); + var code = 'open(' + fn + ', \'' + mode + '\', encoding="' + encode + '")'; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_file_write = function (_, generator) { + var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC); + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + return file + ".write(" + data + ")\n"; +} + +export const storage_get_contents_without_para = function (_, generator) { + var mode = this.getFieldValue('MODE'); + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = file + '.' + mode + '()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_get_contents = function (_, generator) { + var mode = this.getFieldValue('MODE'); + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var size = generator.valueToCode(this, 'SIZE', generator.ORDER_ATOMIC); + var code = file + '.' + mode + '(' + size + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_get_a_line = function (_, generator) { + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var size = generator.valueToCode(this, 'SIZE', generator.ORDER_ATOMIC); + var code = file + ".readline(" + size + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_can_write_ornot = function (_, generator) { + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = file + ".writable()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_get_filename = function (_, generator) { + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = file + ".name()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_close_file = function (_, generator) { + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = file + ".close()\n"; + return code; +} + +export const storage_list_all_files = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var code = 'os.listdir()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_delete_file = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var mode = this.getFieldValue('MODE'); + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = "os." + mode + "(" + file + ")\n"; + return code; +} + +export const storage_get_file_size = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = "os.path.getsize(" + file + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_file_tell = function (_, generator) { + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = file + ".tell()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_file_seek = function (_, generator) { + var mode = this.getFieldValue('MODE'); + var mode_num = 0; + if (mode == 'start') { + mode_num = 0; + } + else if (mode == 'current') { + mode_num = 1; + } + else { + mode_num = 2; + } + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var size = generator.valueToCode(this, 'SIZE', generator.ORDER_ATOMIC); + var code = file + '.seek(' + size + ',' + mode_num + ')\n'; + return code; +} + +export const storage_change_dir = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var code = "os.chdir(" + file + ")\n"; + return code; +} + +export const storage_get_current_dir = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var code = 'os.getcwd()'; + return [code, generator.ORDER_ATOMIC]; +} + +export const storage_make_dir = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var mode = this.getFieldValue('MODE'); + var path = generator.valueToCode(this, 'PATH', generator.ORDER_ATOMIC); + var code = 'os.' + mode + '(' + path + ')\n'; + return code; +} + +export const storage_rename = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var file1 = generator.valueToCode(this, 'NEWFILE', generator.ORDER_ATOMIC); + var code = "os.rename(" + file + "," + file1 + ")\n"; + return code; +} + +export const storage_is_file = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var file = generator.valueToCode(this, 'FILE', generator.ORDER_ATOMIC); + var mode = this.getFieldValue('MODE'); + var code = "os." + mode + "(" + file + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const sdcard_use_spi_init = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + generator.definitions_['import_sdcard'] = 'import sdcard'; + var v = generator.valueToCode(this, 'SUB', generator.ORDER_ATOMIC); + var sv = generator.valueToCode(this, 'SPISUB', generator.ORDER_ATOMIC); + var pv = generator.valueToCode(this, 'PINSUB', generator.ORDER_ATOMIC); + var code = v + ' = sdcard.SDCard(' + sv + ',' + pv + ')\n'; + return code; +} + +export const sdcard_mount = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + generator.definitions_['import_sdcard'] = 'import sdcard'; + var sd = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var dir = generator.valueToCode(this, 'DIR', generator.ORDER_ATOMIC); + return "os.mount(" + sd + ',' + dir + ")\n"; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/text.js b/mixly/boards/default_src/python/generators/text.js new file mode 100644 index 00000000..522ebf6f --- /dev/null +++ b/mixly/boards/default_src/python/generators/text.js @@ -0,0 +1,250 @@ +import * as Blockly from 'blockly/core'; + +export const text = function (_, generator) { + // Text value. + //var code = 'String('+generator.quote_(this.getFieldValue('TEXT'))+')'; + var code = generator.quote_(this.getFieldValue('TEXT')); + return [code, generator.ORDER_ATOMIC]; +} + +export const text_textarea = function (_, generator) { + // Text value. + //var code = 'String('+generator.quote_(this.getFieldValue('TEXT'))+')'; + var code = '"""' + (this.getFieldValue('VALUE')) + '"""'; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_bytes = function (_, generator) { + const text = this.getFieldValue('TEXT'); + return [`b'${text}'`, generator.ORDER_ATOMIC]; +} + +export const text_char = function (_, generator) { + var code = '\'' + this.getFieldValue('TEXT') + '\''; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_join = function (_, generator) { + // Text value. + var a = generator.valueToCode(this, 'A', generator.ORDER_ATOMIC); + var b = generator.valueToCode(this, 'B', generator.ORDER_ATOMIC); + return [a + ' + ' + b, generator.ORDER_ADDITIVE]; +} + +export const ascii_to_char = function (_, generator) { + var asciivalue = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0' + return ['chr(' + asciivalue + ')', generator.ORDER_ATOMIC]; +} + +export const char_to_ascii = function (_, generator) { + var charvalue = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || 'a'; + return ['ord(' + charvalue + ')', generator.ORDER_ATOMIC]; +} + +export const number_to_text = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0'; + return ['str(' + str + ')', generator.ORDER_ATOMIC]; +} + +export const text_length = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + return ['len(' + str + ')', generator.ORDER_ATOMIC]; +} + +export const text_char_at2 = function (a, generator) { + var c = a.getFieldValue("WHERE") || "FROM_START", + str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + switch (c) { + case "FROM_START": + a = generator.getAdjustedInt(a, "AT"); + return [str + "[" + a + "]", generator.ORDER_ATOMIC]; + case "FROM_END": + a = generator.getAdjustedInt(a, "AT", 1, !0); + return [str + "[" + a + "]", generator.ORDER_ATOMIC]; + case "RANDOM": + generator.definitions_.import_random = "import random"; + return ["random.choice(" + str + ")", generator.ORDER_FUNCTION_CALL]; + } + throw "Unhandled combination (lists_getIndex)."; +} + +export const text_char_at = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + var at = generator.valueToCode(this, 'AT', generator.ORDER_ATOMIC) || 0; + return [str + "[" + at + "]", generator.ORDER_ATOMIC]; +} + +export const text_random_char = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + generator.definitions_.import_random = "import random"; + return ["random.choice(" + str + ")", generator.ORDER_FUNCTION_CALL]; +} + +export const text_equals_starts_ends = function (_, generator) { + var str1 = (generator.valueToCode(this, 'STR1', generator.ORDER_ATOMIC) || '""'); + var str2 = (generator.valueToCode(this, 'STR2', generator.ORDER_ATOMIC) || '""'); + var dowhat = this.getFieldValue('DOWHAT'); + if (dowhat === '===') + return [str1 + ' == ' + str2, generator.ORDER_ATOMIC]; + return [str1 + '.' + dowhat + '(' + str2 + ')', generator.ORDER_ATOMIC]; +} + +export const text_compare_to = function (_, generator) { + var str1 = (generator.valueToCode(this, 'STR1', generator.ORDER_ATOMIC) || '""'); + var str2 = (generator.valueToCode(this, 'STR2', generator.ORDER_ATOMIC) || '""'); + return ['cmp(' + str1 + ',' + str2 + ')', generator.ORDER_ATOMIC]; +} + +export const text_substring2 = function (block, generator) { + // Get sublist. + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + var where1 = block.getFieldValue('WHERE1'); + var where2 = block.getFieldValue('WHERE2'); + switch (where1) { + case 'FROM_START': + var at1 = generator.getAdjustedInt(block, 'AT1'); + if (at1 == '0') { + at1 = ''; + } + break; + case 'FROM_END': + var at1 = generator.getAdjustedInt(block, 'AT1', 0, true); + break; + case 'FIRST': + var at1 = '0'; + break; + default: + throw 'Unhandled option (lists_getSublist)'; + } + switch (where2) { + case 'FROM_START': + var at2 = generator.getAdjustedInt(block, 'AT2'); + break; + case 'FROM_END': + var at2 = generator.getAdjustedInt(block, 'AT2', 0, true); + // Ensure that if the result calculated is 0 that sub-sequence will + // include all elements as expected. + if (!Blockly.isNumber(String(at2))) { + generator.definitions_['import_sys'] = 'import sys'; + at2 += ' or sys.maxsize'; + } else if (at2 == '0') { + at2 = ''; + } + break; + case 'LAST': + var at2 = '-1'; + break; + default: + throw 'Unhandled option (lists_getSublist)'; + } + var code = str + '[' + at1 + ' : ' + at2 + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_substring = function (_, generator) { + // Get sublist. + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + var at1 = generator.valueToCode(this, 'AT1', generator.ORDER_ATOMIC); + var at2 = generator.valueToCode(this, 'AT2', generator.ORDER_ATOMIC); + var code = str + '[' + at1 + ' : ' + at2 + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_capital = function (_, generator) { + var capital = this.getFieldValue('CAPITAL'); + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + return ['' + str + '.' + capital + '()', generator.ORDER_ATOMIC]; +} + +export const text_center = function (_, generator) { + var center = this.getFieldValue('CENTER'); + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var width = generator.valueToCode(this, 'WID', generator.ORDER_ATOMIC); + var symbol = generator.valueToCode(this, 'Symbol', generator.ORDER_ATOMIC); + return ['' + str + '.' + center + '(' + width + ',' + symbol + ')', generator.ORDER_ATOMIC]; +} + +export const text_find = function (_, generator) { + var sentence = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var str = generator.valueToCode(this, 'STR', generator.ORDER_ATOMIC); + return ['' + sentence + '.find(' + str + ')', generator.ORDER_ATOMIC]; +} + +export const text_join_seq = function (_, generator) { + var sentence = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var varName = generator.valueToCode(this, 'LIST', generator.ORDER_ASSIGNMENT) || '0'; + return [sentence + '.join(' + varName + ')', generator.ORDER_ATOMIC]; +} + +export const text_replace = function (_, generator) { + var sentence = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var str1 = generator.valueToCode(this, 'STR1', generator.ORDER_ATOMIC); + var str2 = generator.valueToCode(this, 'STR2', generator.ORDER_ATOMIC); + return ['' + sentence + '.replace(' + str1 + ',' + str2 + ')', generator.ORDER_ATOMIC]; +} + +export const text_split = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + var argument = generator.valueToCode(this, 'VAL', generator.ORDER_ATOMIC) || '""'; + var code = str + ".split(" + argument + ")"; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_strip = function (_, generator) { + var towhat = this.getFieldValue('TOWHAT'); + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = str + "." + towhat + "()"; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_format = function (_, generator) { + // Create a list with any number of elements of any type. + var s = this.getFieldValue('VAR'); + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + var code = s + '.format(' + code.join(', ') + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_format_noreturn = function (_, generator) { + // Create a list with any number of elements of any type. + var s = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + var code = s + '.format(' + code.join(', ') + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const text_substring3 = text_substring +export const text_compareTo = text_compare_to +export const text_char_at3 = text_char_at + +export const text_encode = function (_, generator) { + var code = this.getFieldValue('DIR'); + var varName = this.getFieldValue('CODE') + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '""'; + return [str + '.' + code + '("' + varName + '")', generator.ORDER_ATOMIC]; +} + +export const text_eval = function (_, generator) { + var codestr = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "eval" + '(' + codestr + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const os_system = function (_, generator) { + generator.definitions_['import_os'] = 'import os'; + var codestr = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC); + var code = "os.system" + '(' + codestr + ')\n'; + return code; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/tuple.js b/mixly/boards/default_src/python/generators/tuple.js new file mode 100644 index 00000000..8e0649a7 --- /dev/null +++ b/mixly/boards/default_src/python/generators/tuple.js @@ -0,0 +1,306 @@ +import * as Blockly from 'blockly/core'; + +export const tuple_create_with = function (_, generator) { + // Create a list with any number of elements of any type. + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var code = new Array(this.itemCount_); + var default_value = '0'; + for (var n = 0; n < this.itemCount_; n++) { + + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + // if (this.itemCount_!=1){ + // generator.definitions_['var_declare'+varName] = varName+'= '+ '(' + code.join(', ') + ')\n';} + // else { + // generator.definitions_['var_declare'+varName] = varName+'= '+ '(' + code.join(', ') + ',)\n';} + if (this.itemCount_ != 1) { + var code = varName + '= ' + '(' + code.join(', ') + ')\n'; + } + else { + var code = varName + '= ' + '(' + code.join(', ') + ',)\n'; + } + return code; +} + +export const tuple_create_with_text2 = function (_, generator) { + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + //var size=window.parseFloat(this.getFieldValue('SIZE')); + var text = this.getFieldValue('TEXT'); + //generator.definitions_['var_declare'+varName] = varName+'= '+ '(' + text + ')\n'; + var code = varName + '= ' + '(' + text + ')\n'; + return code; +} + +export const tuple_create_with_text_return = function (_, generator) { + var text = this.getFieldValue('TEXT'); + var code = '(' + text + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_getIndex = function (_, generator) { + // Indexing into a list is the same as indexing into a string. + var varName = generator.valueToCode(this, 'TUP', generator.ORDER_ASSIGNMENT) || '0'; + var argument0 = generator.valueToCode(this, 'AT', + generator.ORDER_ADDITIVE) || '1'; + if (argument0.match(/^\d+$/)) { + // If the index is a naked number, decrement it right now. + argument0 = parseInt(argument0, 10); + } + // else { + // If the index is dynamic, decrement it in code. + // argument0; + // } + var code = varName + '[' + argument0 + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_length = function (_, generator) { + var varName = generator.valueToCode(this, 'TUP', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'len(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_del = function (_, generator) { + var varName = generator.valueToCode(this, 'TUP', generator.ORDER_ASSIGNMENT) || '0'; + var code = 'del ' + varName + '\n'; + return code; +} + +export const tuple_join = function (_, generator) { + var varName1 = generator.valueToCode(this, 'TUP1', generator.ORDER_ASSIGNMENT) || '0'; + var varName2 = generator.valueToCode(this, 'TUP2', generator.ORDER_ASSIGNMENT) || '0'; + var code = varName1 + " + " + varName2; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_max = function (_, generator) { + var varname = generator.valueToCode(this, 'TUP', generator.ORDER_ASSIGNMENT) || '0'; + var maxmin = this.getFieldValue('DIR'); + var code = maxmin + "(" + varname + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_change_to = function (_, generator) { + var op = this.getFieldValue('OP'); + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var code = op + '(' + varName + ')\n'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_find = function (_, generator) { + var op = this.getFieldValue('OP'); + var varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '0'; + var argument = generator.valueToCode(this, 'data', generator.ORDER_ASSIGNMENT) || '0'; + if (op == 'INDEX') + var code = varName + '.index(' + argument + ')'; + else if (op == 'COUNT') + var code = varName + '.count(' + argument + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_trig = function (a, generator) { + var b = a.getFieldValue("OP"), c; + generator.definitions_['import_math'] = "import math"; + a = generator.valueToCode(a, 'data', generator.ORDER_NONE) + switch (b) { + case "LEN": + c = "len(" + a + ")"; + break; + case "SUM": + c = "sum(" + a + ")"; + break; + case "MIN": + c = "min(" + a + ")"; + break; + case "MAX": + c = "max(" + a + ")"; + break; + case 'AVERAGE': + // generator.definitions_['from_numbers_import_Number'] = + // 'from numbers import Number'; + var functionName = generator.provideFunction_( + 'math_mean', + // This operation excludes null and values that aren't int or float:', + // math_mean([null, null, "aString", 1, 9]) == 5.0.', + ['def ' + generator.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' localList = [e for e in myList if type(e) == int or type(e) == float]', + ' if not localList: return', + ' return float(sum(localList)) / len(localList)']); + c = functionName + '(' + a + ')'; + break; + case 'MEDIAN': + // generator.definitions_['from_numbers_import_Number'] = + // 'from numbers import Numberd'; + var functionName = generator.provideFunction_( + 'math_median', + // This operation excludes null values: + // math_median([null, null, 1, 3]) == 2.0. + ['def ' + generator.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' localList = sorted([e for e in myList if type(e) == int or type(e) == float])', + ' if not localList: return', + ' if len(localList) % 2 == 0:', + ' return (localList[len(localList) // 2 - 1] + ' + + 'localList[len(localList) // 2]) / 2.0', + ' else:', + ' return localList[(len(localList) - 1) // 2]']); + c = functionName + '(' + a + ')'; + break; + case 'MODE': + var functionName = generator.provideFunction_( + 'math_modes', + // As a list of numbers can contain more than one mode, + // the returned result is provided as an array. + // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. + ['def ' + generator.FUNCTION_NAME_PLACEHOLDER_ + '(some_list):', + ' modes = []', + ' # Using a lists of [item, count] to keep count rather than dict', + ' # to avoid "unhashable" errors when the counted item is ' + + 'itself a list or dict.', + ' counts = []', + ' maxCount = 1', + ' for item in some_list:', + ' found = False', + ' for count in counts:', + ' if count[0] == item:', + ' count[1] += 1', + ' maxCount = max(maxCount, count[1])', + ' found = True', + ' if not found:', + ' counts.append([item, 1])', + ' for counted_item, item_count in counts:', + ' if item_count == maxCount:', + ' modes.append(counted_item)', + ' return modes']); + c = functionName + '(' + a + ')'; + break; + case 'STD_DEV': + generator.definitions_['import_math'] = 'import math'; + var functionName = generator.provideFunction_( + 'math_standard_deviation', + ['def ' + generator.FUNCTION_NAME_PLACEHOLDER_ + '(numbers):', + ' n = len(numbers)', + ' if n == 0: return', + ' mean = float(sum(numbers)) / n', + ' variance = sum((x - mean) ** 2 for x in numbers) / n', + ' return math.sqrt(variance)']); + c = functionName + '(' + a + ')'; + break; + default: + throw 'Unknown operator: ' + b; + } + if (c) + return [c, generator.ORDER_FUNCTION_CALL]; + +} + +export const tuple_getSublist = function (block, generator) { + // Get sublist. + var list = generator.valueToCode(block, 'LIST', + generator.ORDER_MEMBER) || '[]'; + var where1 = block.getFieldValue('WHERE1'); + var where2 = block.getFieldValue('WHERE2'); + switch (where1) { + case 'FROM_START': + var at1 = generator.getAdjustedInt(block, 'AT1'); + if (at1 == '0') { + at1 = ''; + } + break; + case 'FROM_END': + var at1 = generator.getAdjustedInt(block, 'AT1', 1, true); + break; + case 'FIRST': + var at1 = '0'; + break; + default: + throw 'Unhandled option (lists_getSublist)'; + } + switch (where2) { + case 'FROM_START': + var at2 = generator.getAdjustedInt(block, 'AT2', 1); + at2 = at2 - 1; + break; + case 'FROM_END': + var at2 = generator.getAdjustedInt(block, 'AT2', 1, true); + // Ensure that if the result calculated is 0 that sub-sequence will + // include all elements as expected. + if (!Blockly.isNumber(String(at2))) { + generator.definitions_['import_sys'] = 'import sys'; + at2 += ' or sys.maxsize'; + } else if (at2 == '0') { + at2 = ''; + } + break; + case 'LAST': + var at2 = '-1'; + break; + default: + throw 'Unhandled option (lists_getSublist)'; + } + var code = list + '[' + at1 + ' : ' + at2 + ']'; + return [code, generator.ORDER_MEMBER]; +} + +export const tuple_create_with_noreturn = function (_, generator) { + // Create a list with any number of elements of any type. + var code = new Array(this.itemCount_); + var default_value = '0'; + + + for (var n = 0; n < this.itemCount_; n++) { + + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + // if (this.itemCount_!=1){ + // generator.definitions_['var_declare'+varName] = varName+'= '+ '(' + code.join(', ') + ')\n';} + // else { + // generator.definitions_['var_declare'+varName] = varName+'= '+ '(' + code.join(', ') + ',)\n';} + if (this.itemCount_ != 1) { + var code = '(' + code.join(', ') + ')'; + } + else { + var code = '(' + code.join(', ') + ',)'; + } + + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_get_sublist = function (_, generator) { + // Get sublist. + var list = generator.valueToCode(this, 'LIST', generator.ORDER_ADDITIVE) || '0'; + var at1 = generator.valueToCode(this, 'AT1', generator.ORDER_ADDITIVE) || '0'; + var at2 = generator.valueToCode(this, 'AT2', generator.ORDER_ADDITIVE) || '0'; + var code = list + '[' + at1 + ' : ' + at2 + ']'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_get_random_item = function (_, generator) { + generator.definitions_['import_random'] = 'import random'; + var varName = generator.valueToCode(this, 'TUP', generator.ORDER_ADDITIVE) || 'mytup'; + var code = 'random.choice(' + varName + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_totuple = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || '0' + return ['tuple(' + str + ')', generator.ORDER_ATOMIC]; +} + +export const tuple_input = function (_, generator) { + var text = this.getFieldValue('CONTENT'); + var code = '(' + text + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const tuple_create_llm_params = function (_, generator) { + var params = generator.valueToCode(this, 'params', generator.ORDER_ATOMIC) || '0' + var des = generator.valueToCode(this, 'des', generator.ORDER_ATOMIC) || '0' + var type = this.getFieldValue('type'); + var code = '(' + params + ',"' + type + '",' + des +')'; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/utility.js b/mixly/boards/default_src/python/generators/utility.js new file mode 100644 index 00000000..467c01c3 --- /dev/null +++ b/mixly/boards/default_src/python/generators/utility.js @@ -0,0 +1,78 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for utility blocks. + * @author acbart@vt.edu (Austin Cory Bart) + */ + +export const raw_block = function (block) { + var code = block.getFieldValue('TEXT') + "\n"; + return code; +} + +export const raw_expression = function (block, generator) { + var code = block.getFieldValue('TEXT'); + return [code, generator.ORDER_ATOMIC]; +} + +export const raw_empty = function (block, generator) { + var code = generator.valueToCode(block, 'VALUE', + generator.ORDER_ATOMIC) || ''; + return code + "\n"; +} + +export const raw_table = function () { + //var code = block.getFieldValue('TEXT')+"\n"; + return '';//code; +} + +export const type_check = function (block, generator) { + var value = generator.valueToCode(block, 'VALUE', + generator.ORDER_MEMBER) || '___'; + var code = 'type(' + value + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const function_call = function (block, generator) { + var name = block.getFieldValue('NAME'); + var hasReturn = block.hasReturn_; + var args = new Array(block.itemCount_); + for (var n = 0; n < block.itemCount_; n++) { + args[n] = generator.valueToCode(block, 'ARGUMENT' + n, + generator.ORDER_NONE) || '___'; + } + var code = name + '(' + args.join(', ') + ')'; + if (hasReturn) { + return [code, generator.ORDER_ATOMIC]; + } + return code + '\n'; +} + +export const attribute_access = function (block, generator) { + var value_module = generator.valueToCode(block, 'MODULE', generator.ORDER_ATOMIC); + var value_name = generator.valueToCode(block, 'NAME', generator.ORDER_ATOMIC); + //去除掉两端的括号,如(val()) --> val() + value_name = value_name.substring(1, value_name.length - 1); + // TODO: Assemble JavaScript into code variable. + var code = value_module + '.' + value_name; + // TODO: Change ORDER_NONE to the correct strength. + return [code, generator.ORDER_NONE]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/generators/variables.js b/mixly/boards/default_src/python/generators/variables.js new file mode 100644 index 00000000..512dc26d --- /dev/null +++ b/mixly/boards/default_src/python/generators/variables.js @@ -0,0 +1,90 @@ +import * as Blockly from 'blockly/core'; + +export const variables_get = function (_, generator) { + // Variable getter. + var code = generator.variableDB_.getName(this.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + return [code, generator.ORDER_ATOMIC]; +} + +// export const variables_declare = function() { +// var dropdown_type = this.getFieldValue('TYPE'); +// var argument0; +// //TODO: settype to variable +// argument0 = generator.valueToCode(this, 'VALUE',generator.ORDER_ASSIGNMENT) || 'None'; +// var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), +// Blockly.Variables.NAME_TYPE); + +// if (dropdown_type === 'number') +// generator.definitions_['var_declare' + varName] = 'let ' + ' ' + varName + ' = 0;'; +// else if(dropdown_type === 'string') +// generator.definitions_['var_declare' + varName] = 'let ' + ' ' + varName + ' = \'\';'; +// else if(dropdown_type === 'boolean') +// generator.definitions_['var_declare' + varName] = 'let ' + ' ' + varName + ' = true;'; +// else if(dropdown_type.startsWith('Array')) +// generator.definitions_['var_declare' + varName] = 'let ' + varName + ':' + dropdown_type + ' = [];'; + +// if(generator.setups_['var_declare' + varName] === undefined) { +// generator.setups_['var_declare' + varName] = varName + ' = ' + argument0 + '\n'; +// }else { +// } +// return ''; +// } + +export const variables_set = function (_, generator) { + // Variable setter. + if (this.getFieldValue('VAR') == "") { + return " = None\n"; + } + var argument0 = generator.valueToCode(this, 'VALUE', + generator.ORDER_ASSIGNMENT) || 'None'; + var varName = generator.variableDB_.getName(this.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + return varName + ' = ' + argument0 + '\n'; +} + +export const variables_change = function (_, generator) { + // Variable setter. + var operator = this.getFieldValue('OP'); + var varName = generator.valueToCode(this, 'MYVALUE', generator.ORDER_ATOMIC) || 'None'; + if (operator == 'bytes') { var code = operator + '(' + varName + ',"UTF-8")'; } + else { var code = operator + '(' + varName + ')'; } + return [code, generator.ORDER_ATOMIC]; +} + +export const variables_global = function (_, generator) { + var str = generator.valueToCode(this, 'VAR', generator.ORDER_ATOMIC) || 'None'; + var code = "global " + str + '\n'; + return code; +} + +// ok +export const controls_type = function (_, generator) { + var data = generator.valueToCode(this, 'DATA', generator.ORDER_ATOMIC) || 'None' + var code = 'type(' + data + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const controls_typeLists = function (_, generator) { + //generator.definitions_['import_microbit_*'] = 'from microbit import *'; + var type = this.getFieldValue('type'); + // generator.definitions_['func_type' + type] = code; + return [type, generator.ORDER_ATOMIC]; +} + +export const lists_zip = function (_, generator) { + var code = new Array(this.itemCount_); + var default_value = '[]'; + for (var n = 0; n < this.itemCount_; n++) { + code[n] = generator.valueToCode(this, 'ADD' + n, + generator.ORDER_NONE) || default_value; + } + var code = 'zip(' + code.join(', ') + ')'; + return [code, generator.ORDER_ATOMIC]; +} + +export const unpack_iterable_object = function (_, generator) { + const varName = generator.valueToCode(this, 'VAR', generator.ORDER_ASSIGNMENT) || '[]'; + const type = this.getFieldValue('TYPE'); + const code = `${type}(${varName})`; + return [code, generator.ORDER_ATOMIC]; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/index.js b/mixly/boards/default_src/python/index.js new file mode 100644 index 00000000..e69de29b diff --git a/mixly/boards/default_src/python/others/class.js b/mixly/boards/default_src/python/others/class.js new file mode 100644 index 00000000..97a487f0 --- /dev/null +++ b/mixly/boards/default_src/python/others/class.js @@ -0,0 +1,722 @@ +/** + * @license + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Utility functions for handling class_test. + * @author fraser@google.com (Neil Fraser) + */ + +import * as Blockly from 'blockly/core'; + +//类 +Blockly.Block.prototype.class_getVars = function () { for (var a = [], b = 0, c; c = this.inputList[b]; b++)for (var d = 0, e; e = c.fieldRow[d]; d++)e instanceof Blockly.FieldVariable && a.push(e.getValue()); return a }; Blockly.Block.prototype.class_renameVar = function (a, b) { for (var c = 0, d; d = this.inputList[c]; c++)for (var e = 0, f; f = d.fieldRow[e]; e++)f instanceof Blockly.FieldVariable && Blockly.Names.equals(a, f.getValue()) && f.setValue(b) }; +//属性 +Blockly.Block.prototype.property_getVars = function () { for (var a = [], b = 0, c; c = this.inputList[b]; b++)for (var d = 0, e; e = c.fieldRow[d]; d++)e instanceof Blockly.FieldVariable && a.push(e.getValue()); return a }; Blockly.Block.prototype.property_renameVar = function (a, b) { for (var c = 0, d; d = this.inputList[c]; c++)for (var e = 0, f; f = d.fieldRow[e]; e++)f instanceof Blockly.FieldVariable && Blockly.Names.equals(a, f.getValue()) && f.setValue(b) }; +//对象 +Blockly.Block.prototype.object_getVars = function () { for (var a = [], b = 0, c; c = this.inputList[b]; b++)for (var d = 0, e; e = c.fieldRow[d]; d++)e instanceof Blockly.FieldVariable && a.push(e.getValue()); return a }; Blockly.Block.prototype.object_renameVar = function (a, b) { for (var c = 0, d; d = this.inputList[c]; c++)for (var e = 0, f; f = d.fieldRow[e]; e++)f instanceof Blockly.FieldVariable && Blockly.Names.equals(a, f.getValue()) && f.setValue(b) }; + +//类 +Blockly.Class.CLASS_NAME_TYPE = 'CLASS'; +//属性 +Blockly.Class.PROPERTY_NAME_TYPE = 'PROPERTY'; +//方法 +Blockly.Class.METHOD_NAME_TYPE = 'METHOD'; +//对象 +Blockly.Class.OBJECT_NAME_TYPE = 'OBJECT'; + + +/**** 类 ****/ +Blockly.Class.allClass = function (root) { + var blocks; + if (root.getDescendants) { + // Root is Block. + blocks = root.getDescendants(); + } else if (root.getAllBlocks) { + // Root is Workspace. + blocks = root.getAllBlocks(); + } else { + throw 'Not Block or Workspace: ' + root; + } + var variableHash = Object.create(null); + // Iterate through every block and add each variable to the hash. + for (var x = 0; x < blocks.length; x++) { + var blockClass = blocks[x].class_getVars(); + for (var y = 0; y < blockClass.length; y++) { + var varName = blockClass[y]; + // Variable name may be null if the block is only half-built. + if (varName) { + variableHash[varName.toLowerCase()] = varName; + } + } + } + // Flatten the hash into a list. + var variableList = []; + for (var name in variableHash) { + variableList.push(variableHash[name]); + } + return variableList; +}; + +Blockly.Class.renameClass = function (oldName, newName, workspace) { + Blockly.Events.setGroup(true); + var blocks = workspace.getAllBlocks(); + // Iterate through every block. + for (var i = 0; i < blocks.length; i++) { + blocks[i].class_renameVar(oldName, newName); + } + Blockly.Events.setGroup(false); +}; + +Blockly.Class.class_generateUniqueName = function (workspace) { + var variableList = Blockly.Class.allClass(workspace); + var newName = ''; + if (variableList.length) { + var nameSuffix = 1; + var letters = 'ijkmnopqrstuvwxyzabcdefgh'; // No 'l'. + var letterIndex = 0; + var potName = letters.charAt(letterIndex); + while (!newName) { + var inUse = false; + for (var i = 0; i < variableList.length; i++) { + if (variableList[i].toLowerCase() == potName) { + // This potential name is already used. + inUse = true; + break; + } + } + if (inUse) { + // Try the next potential name. + letterIndex++; + if (letterIndex == letters.length) { + // Reached the end of the character sequence so back to 'i'. + // a new suffix. + letterIndex = 0; + nameSuffix++; + } + potName = letters.charAt(letterIndex); + if (nameSuffix > 1) { + potName += nameSuffix; + } + } else { + // We can use the current potential name. + newName = potName; + } + } + } else { + newName = 'i'; + } + return newName; +}; + +Blockly.Class.class_flyoutCategory = function (workspace) { + var variableList = Blockly.Class.allClass(workspace); + //variableList.sort(goog.string.caseInsensitiveCompare); + + var xmlList = []; + + //创建类 + if (Blockly.Blocks['class_make']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'class_make'); + if (Blockly.Blocks['class_make']) { + block.setAttribute('gap', 16); + } + xmlList.push(block); + } + if (Blockly.Blocks['class_make_with_base']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'class_make_with_base'); + if (Blockly.Blocks['class_make_with_base']) { + block.setAttribute('gap', 16); + } + xmlList.push(block); + } + + if (xmlList.length) { + xmlList[xmlList.length - 1].setAttribute('gap', 30); + } + + for (var i = 0; i < variableList.length; i++) { + if (Blockly.Blocks['class_get']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'class_get'); + if (Blockly.Blocks['class_get']) { + block.setAttribute('gap', 16); + } + var field = Blockly.utils.xml.createElement('field', null, variableList[i]); + field.setAttribute('name', 'VAR'); + block.appendChild(field); + xmlList.push(block); + } + } + return xmlList; +}; + + +/**** 属性 ****/ +Blockly.Class.allProperty = function (root) { + var blocks; + if (root.getDescendants) { + // Root is Block. + blocks = root.getDescendants(); + } else if (root.getAllBlocks) { + // Root is Workspace. + blocks = root.getAllBlocks(); + } else { + throw 'Not Block or Workspace: ' + root; + } + var variableHash = Object.create(null); + // Iterate through every block and add each variable to the hash. + for (var x = 0; x < blocks.length; x++) { + var blockClass = blocks[x].property_getVars(); + for (var y = 0; y < blockClass.length; y++) { + var varName = blockClass[y]; + // Variable name may be null if the block is only half-built. + if (varName) { + variableHash[varName.toLowerCase()] = varName; + } + } + } + // Flatten the hash into a list. + var variableList = []; + for (var name in variableHash) { + variableList.push(variableHash[name]); + } + return variableList; +}; + +Blockly.Class.renameProperty = function (oldName, newName, workspace) { + Blockly.Events.setGroup(true); + var blocks = workspace.getAllBlocks(); + // Iterate through every block. + for (var i = 0; i < blocks.length; i++) { + blocks[i].property_renameVar(oldName, newName); + } + Blockly.Events.setGroup(false); +}; + +Blockly.Class.property_generateUniqueName = function (workspace) { + var variableList = Blockly.Class.allProperty(workspace); + var newName = ''; + if (variableList.length) { + var nameSuffix = 1; + var letters = 'ijkmnopqrstuvwxyzabcdefgh'; // No 'l'. + var letterIndex = 0; + var potName = letters.charAt(letterIndex); + while (!newName) { + var inUse = false; + for (var i = 0; i < variableList.length; i++) { + if (variableList[i].toLowerCase() == potName) { + // This potential name is already used. + inUse = true; + break; + } + } + if (inUse) { + // Try the next potential name. + letterIndex++; + if (letterIndex == letters.length) { + // Reached the end of the character sequence so back to 'i'. + // a new suffix. + letterIndex = 0; + nameSuffix++; + } + potName = letters.charAt(letterIndex); + if (nameSuffix > 1) { + potName += nameSuffix; + } + } else { + // We can use the current potential name. + newName = potName; + } + } + } else { + newName = 'i'; + } + return newName; +}; + +Blockly.Class.property_flyoutCategory = function (workspace) { + var variableList = Blockly.Class.allProperty(workspace); + //variableList.sort(goog.string.caseInsensitiveCompare); + + var xmlList = []; + + //创建属性 + if (Blockly.Blocks['property_set']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'property_set'); + xmlList.push(block); + } + + if (xmlList.length) { + xmlList[xmlList.length - 1].setAttribute('gap', 30); + } + + for (var i = 0; i < variableList.length; i++) { + if (Blockly.Blocks['property_set']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'property_set'); + if (Blockly.Blocks['property_set']) { + block.setAttribute('gap', 16); + } + var field = Blockly.utils.xml.createElement('field', null, variableList[i]); + field.setAttribute('name', 'VAR'); + block.appendChild(field); + xmlList.push(block); + } + if (Blockly.Blocks['property_get']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'property_get'); + if (Blockly.Blocks['property_get']) { + block.setAttribute('gap', 25); + } + var field = Blockly.utils.xml.createElement('field', null, variableList[i]); + field.setAttribute('name', 'VAR'); + block.appendChild(field); + xmlList.push(block); + } + } + return xmlList; +}; + + +/**** 方法 ****/ +Blockly.Class.proallProcedures = function (root) { + var blocks = root.getAllBlocks(); + var proceduresReturn = []; + var proceduresNoReturn = []; + var name_data = []; + var select = true; + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].method_getProcedureDef) { + var tuple = blocks[i].method_getProcedureDef(); + if (tuple) { + if (tuple[4]) { + if (name_data.length == 0) { + if (tuple[4].indexOf("_") != -1) { + select = true; + name_data.push(tuple[4]); + } + else { + select = false; + } + } + else { + for (var j = 0; j < name_data.length; j++) { + if (name_data[j] == tuple[4] || tuple[4].indexOf("_") == -1) { + select = false; + break; + } + if (j == name_data.length - 1) { + select = true; + name_data.push(tuple[4]); + break; + } + } + } + } + if (select) { + if (tuple[2]) { + proceduresReturn.push(tuple); + } else { + proceduresNoReturn.push(tuple); + } + } + } + } + } + proceduresNoReturn.sort(Blockly.Class.proprocTupleComparator_); + proceduresReturn.sort(Blockly.Class.proprocTupleComparator_); + return [proceduresNoReturn, proceduresReturn]; +}; + +/** + * Comparison function for case-insensitive sorting of the first element of + * a tuple. + * @param {!Array} ta First tuple. + * @param {!Array} tb Second tuple. + * @return {number} -1, 0, or 1 to signify greater than, equality, or less than. + * @private + */ +Blockly.Class.proprocTupleComparator_ = function (ta, tb) { + return ta[0].toLowerCase().localeCompare(tb[0].toLowerCase()); +}; + +/** + * Ensure two identically-named procedures don't exist. + * @param {string} name Proposed procedure name. + * @param {!Blockly.Block} block Block to disambiguate. + * @return {string} Non-colliding name. + */ +Blockly.Class.profindLegalName = function (name, block) { + /* + if (block.isInFlyout) { + // Flyouts can have multiple procedures called 'do something'. + return name; + } + while (!Blockly.Class.proisLegalName(name, block.workspace, block)) { + // Collision with another procedure. + var r = name.match(/^(.*?)(\d+)$/); + if (!r) { + name += '2'; + } else { + name = r[1] + (parseInt(r[2], 10) + 1); + } + name = ''; + } + */ + return name; +}; + +/** + * Does this procedure have a legal name? Illegal names include names of + * procedures already defined. + * @param {string} name The questionable name. + * @param {!Blockly.Workspace} workspace The workspace to scan for collisions. + * @param {Blockly.Block=} opt_exclude Optional block to exclude from + * comparisons (one doesn't want to collide with oneself). + * @return {boolean} True if the name is legal. + */ +Blockly.Class.proisLegalName = function (name, workspace, opt_exclude) { + var blocks = workspace.getAllBlocks(); + // Iterate through every block and check the name. + for (var i = 0; i < blocks.length; i++) { + if (blocks[i] == opt_exclude) { + continue; + } + if (blocks[i].method_getProcedureDef) { + var procName = blocks[i].method_getProcedureDef(); + if (Blockly.Names.equals(procName[0], name)) { + return false; + } + } + } + return true; +}; + +/** + * Rename a procedure. Called by the editable field. + * @param {string} text The proposed new name. + * @return {string} The accepted name. + * @this {!Blockly.Field} + */ +Blockly.Class.prorename = function (text) { + // Strip leading and trailing whitespace. Beyond this, all names are legal. + text = text.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); + + // Ensure two identically-named procedures don't exist. + text = Blockly.Class.profindLegalName(text, this.sourceBlock_); + // Rename any callers. + var blocks = this.sourceBlock_.workspace.getAllBlocks(); + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].method_renameProcedure) { + blocks[i].method_renameProcedure(this.text_, text); + } + } + return text; +}; + +/** + * Find all the callers of a named procedure. + * @param {string} name Name of procedure. + * @param {!Blockly.Workspace} workspace The workspace to find callers in. + * @return {!Array.} Array of caller blocks. + */ +Blockly.Class.progetCallers = function (name, workspace) { + var callers = []; + var blocks = workspace.getAllBlocks(); + // Iterate through every block and check the name. + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].method_getProcedureCall) { + var procName = blocks[i].method_getProcedureCall(); + // Procedure name may be null if the block is only half-built. + if (procName && Blockly.Names.equals(procName, name)) { + callers.push(blocks[i]); + } + } + } + return callers; +}; + +/** + * When a procedure definition is disposed of, find and dispose of all its + * callers. + * @param {string} name Name of deleted procedure definition. + * @param {!Blockly.Workspace} workspace The workspace to delete callers from. + */ +Blockly.Class.prodisposeCallers = function (name, workspace) { + var callers = Blockly.Class.progetCallers(name, workspace); + for (var i = 0; i < callers.length; i++) { + callers[i].dispose(true, false); + } +}; + +/** + * When a procedure definition changes its parameters, find and edit all its + * callers. + * @param {!Blockly.Block} defBlock Procedure definition block. + */ +Blockly.Class.mutateCallers = function (defBlock) { + var oldRecordUndo = Blockly.Events.recordUndo; + var name = defBlock.method_getProcedureDef()[0]; + var xmlElement = defBlock.mutationToDom(true); + var callers = Blockly.Procedures.getCallers(name, defBlock.workspace); + for (var i = 0, caller; caller = callers[i]; i++) { + var oldMutationDom = caller.mutationToDom(); + var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom); + caller.domToMutation(xmlElement); + var newMutationDom = caller.mutationToDom(); + var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom); + if (oldMutation != newMutation) { + // Fire a mutation on every caller block. But don't record this as an + // undo action since it is deterministically tied to the procedure's + // definition mutation. + Blockly.Events.recordUndo = false; + Blockly.Events.fire(new Blockly.Events.BlockChange( + caller, 'mutation', null, oldMutation, newMutation)); + Blockly.Events.recordUndo = oldRecordUndo; + } + } +}; + +/** + * Find the definition block for the named procedure. + * @param {string} name Name of procedure. + * @param {!Blockly.Workspace} workspace The workspace to search. + * @return {Blockly.Block} The procedure definition block, or null not found. + */ +Blockly.Class.progetDefinition = function (name, workspace) { + var blocks = workspace.getAllBlocks(); + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].method_getProcedureDef) { + var tuple = blocks[i].method_getProcedureDef(); + if (tuple && Blockly.Names.equals(tuple[0], name)) { + return blocks[i]; + } + } + } + return null; +}; + +Blockly.Class.method_flyoutCategory = function (workspace) { + var xmlList = []; + //创建方法 + if (Blockly.Blocks['method_procedures_defnoreturn']) { + // + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'method_procedures_defnoreturn'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + if (Blockly.Blocks['method_procedures_defreturn']) { + // + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'method_procedures_defreturn'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + /* + if (Blockly.Blocks['method_procedures_return']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'method_procedures_return'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + if (Blockly.Blocks['method_procedures_ifreturn']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'method_procedures_ifreturn'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + */ + if (Blockly.Blocks['procedures_return']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'procedures_return'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + if (Blockly.Blocks['procedures_ifreturn']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'procedures_ifreturn'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + + function populateProcedures(procedureList, templateName) { + for (var i = 0; i < procedureList.length; i++) { + var name = procedureList[i][0]; + var args = procedureList[i][1]; + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', templateName); + block.setAttribute('gap', 16); + var mutation = Blockly.utils.xml.createElement('mutation'); + mutation.setAttribute('name', name); + block.appendChild(mutation); + for (var t = 0; t < args.length; t++) { + var arg = Blockly.utils.xml.createElement('arg'); + arg.setAttribute('name', args[t]); + mutation.appendChild(arg); + } + xmlList.push(block); + } + } + + var tuple = Blockly.Class.proallProcedures(workspace); + populateProcedures(tuple[0], 'method_procedures_callnoreturn'); + populateProcedures(tuple[1], 'method_procedures_callreturn'); + + return xmlList; +}; + + +/**** 对象 ****/ +Blockly.Class.allObject = function (root) { + var blocks; + if (root.getDescendants) { + // Root is Block. + blocks = root.getDescendants(); + } else if (root.getAllBlocks) { + // Root is Workspace. + blocks = root.getAllBlocks(); + } else { + throw 'Not Block or Workspace: ' + root; + } + var variableHash = Object.create(null); + // Iterate through every block and add each variable to the hash. + for (var x = 0; x < blocks.length; x++) { + var blockClass = blocks[x].object_getVars(); + for (var y = 0; y < blockClass.length; y++) { + var varName = blockClass[y]; + // Variable name may be null if the block is only half-built. + if (varName) { + variableHash[varName.toLowerCase()] = varName; + } + } + } + // Flatten the hash into a list. + var variableList = []; + for (var name in variableHash) { + variableList.push(variableHash[name]); + } + return variableList; +}; + +Blockly.Class.renameObject = function (oldName, newName, workspace) { + Blockly.Events.setGroup(true); + var blocks = workspace.getAllBlocks(); + // Iterate through every block. + for (var i = 0; i < blocks.length; i++) { + blocks[i].object_renameVar(oldName, newName); + } + Blockly.Events.setGroup(false); +}; + +Blockly.Class.object_generateUniqueName = function (workspace) { + var variableList = Blockly.Class.allObject(workspace); + var newName = ''; + if (variableList.length) { + var nameSuffix = 1; + var letters = 'ijkmnopqrstuvwxyzabcdefgh'; // No 'l'. + var letterIndex = 0; + var potName = letters.charAt(letterIndex); + while (!newName) { + var inUse = false; + for (var i = 0; i < variableList.length; i++) { + if (variableList[i].toLowerCase() == potName) { + // This potential name is already used. + inUse = true; + break; + } + } + if (inUse) { + // Try the next potential name. + letterIndex++; + if (letterIndex == letters.length) { + // Reached the end of the character sequence so back to 'i'. + // a new suffix. + letterIndex = 0; + nameSuffix++; + } + potName = letters.charAt(letterIndex); + if (nameSuffix > 1) { + potName += nameSuffix; + } + } else { + // We can use the current potential name. + newName = potName; + } + } + } else { + newName = 'i'; + } + return newName; +}; + +Blockly.Class.object_flyoutCategory = function (workspace) { + var variableList = Blockly.Class.allObject(workspace); + //variableList.sort(goog.string.caseInsensitiveCompare); + + var xmlList = []; + + //创建对象 + if (Blockly.Blocks['object_set']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'object_set'); + xmlList.push(block); + } + + if (xmlList.length) { + xmlList[xmlList.length - 1].setAttribute('gap', 30); + } + + var variableList_class = Blockly.Class.allClass(workspace); + //variableList_class.sort(goog.string.caseInsensitiveCompare); + for (var i = 0; i < variableList_class.length; i++) { + if (Blockly.Blocks['object_set']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'object_set'); + if (Blockly.Blocks['object_set']) { + block.setAttribute('gap', 16); + } + var field = Blockly.utils.xml.createElement('field', null, variableList_class[i]); + field.setAttribute('name', 'VAR10'); + block.appendChild(field); + xmlList.push(block); + } + } + + for (var i = 0; i < variableList.length; i++) { + if (Blockly.Blocks['object_get']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'object_get'); + if (Blockly.Blocks['object_get']) { + block.setAttribute('gap', 16); + } + var field = Blockly.utils.xml.createElement('field', null, variableList[i]); + field.setAttribute('name', 'VAR'); + block.appendChild(field); + xmlList.push(block); + } + } + + return xmlList; +}; + diff --git a/mixly/boards/default_src/python/others/names.js b/mixly/boards/default_src/python/others/names.js new file mode 100644 index 00000000..5361c676 --- /dev/null +++ b/mixly/boards/default_src/python/others/names.js @@ -0,0 +1,192 @@ +/** + * @license + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Utility functions for handling variables and procedure names. + * @author fraser@google.com (Neil Fraser) + */ +import Variables from './variables'; + +/** + * Class for a database of entity names (variables, functions, etc). + * @param {string} reservedWords A comma-separated string of words that are + * illegal for use as names in a language (e.g. 'new,if,this,...'). + * @param {string=} opt_variablePrefix Some languages need a '$' or a namespace + * before all variable names. + * @constructor + */ +class Names { + constructor(reservedWords, opt_variablePrefix) { + this.variablePrefix_ = opt_variablePrefix || ''; + this.reservedDict_ = Object.create(null); + if (reservedWords) { + var splitWords = reservedWords.split(','); + for (var i = 0; i < splitWords.length; i++) { + this.reservedDict_[splitWords[i]] = true; + } + } + this.reset(); + } + /** + * Do the given two entity names refer to the same entity? + * Blockly names are case-insensitive. + * @param {string} name1 First name. + * @param {string} name2 Second name. + * @return {boolean} True if names are the same. + */ + static equals(name1, name2) { + return name1 == name2; + } + /** + * When JavaScript (or most other languages) is generated, variable 'foo' and + * procedure 'foo' would collide. However, Blockly has no such problems since + * variable get 'foo' and procedure call 'foo' are unambiguous. + * Therefore, Blockly keeps a separate type name to disambiguate. + * getName('foo', 'variable') -> 'foo' + * getName('foo', 'procedure') -> 'foo2' + */ + /** + * Empty the database and start from scratch. The reserved words are kept. + */ + reset() { + this.db_ = Object.create(null); + this.dbReverse_ = Object.create(null); + this.variableMap_ = null; + } + /** + * Set the variable map that maps from variable name to variable object. + * @param {!Blockly.VariableMap} map The map to track. + * @package + */ + setVariableMap(map) { + this.variableMap_ = map; + } + /** + * Get the name for a user-defined variable, based on its ID. + * This should only be used for variables of type Variables.NAME_TYPE. + * @param {string} id The ID to look up in the variable map. + * @return {?string} The name of the referenced variable, or null if there was + * no variable map or the variable was not found in the map. + * @private + */ + getNameForUserVariable_(id) { + if (!this.variableMap_) { + /* + console.log('Deprecated call to Names.prototype.getName without ' + + 'defining a variable map. To fix, add the folowing code in your ' + + 'generator\'s init() function:\n' + + 'Blockly.YourGeneratorName.variableDB_.setVariableMap(' + + 'workspace.getVariableMap());'); + */ + return null; + } + var variable = this.variableMap_.getVariableById(id); + if (variable) { + return variable.name; + } + return null; + } + /** + * Convert a Blockly entity name to a legal exportable entity name. + * @param {string} name The Blockly entity name (no constraints). + * @param {string} type The type of entity in Blockly + * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). + * @return {string} An entity name that is legal in the exported language. + */ + getName(name, type) { + if (type == Variables.NAME_TYPE) { + var varName = this.getNameForUserVariable_(name); + if (varName) { + name = varName; + } + } + var normalized = name + '_' + type; + + var isVarType = type == Variables.NAME_TYPE || + type == Names.DEVELOPER_VARIABLE_TYPE; + + var prefix = isVarType ? this.variablePrefix_ : ''; + if (normalized in this.db_) { + return prefix + this.db_[normalized]; + } + var safeName = this.getDistinctName(name, type); + this.db_[normalized] = safeName.substr(prefix.length); + return safeName; + } + /** + * Convert a Blockly entity name to a legal exportable entity name. + * Ensure that this is a new name not overlapping any previously defined name. + * Also check against list of reserved words for the current language and + * ensure name doesn't collide. + * @param {string} name The Blockly entity name (no constraints). + * @param {string} type The type of entity in Blockly + * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). + * @return {string} An entity name that is legal in the exported language. + */ + getDistinctName(name, type) { + var safeName = this.safeName_(name); + var i = ''; + while (this.dbReverse_[safeName + i] || + (safeName + i) in this.reservedDict_) { + // Collision with existing name. Create a unique name. + i = i ? i + 1 : 2; + } + safeName += i; + this.dbReverse_[safeName] = true; + var isVarType = type == Variables.NAME_TYPE || + type == Names.DEVELOPER_VARIABLE_TYPE; + var prefix = isVarType ? this.variablePrefix_ : ''; + return prefix + safeName; + } + /** + * Given a proposed entity name, generate a name that conforms to the + * [_A-Za-z][_A-Za-z0-9]* format that most languages consider legal for + * variables. + * @param {string} name Potentially illegal entity name. + * @return {string} Safe entity name. + * @private + */ + safeName_(name) { + if (!name) { + name = 'unnamed'; + } else { + // Unfortunately names in non-latin characters will look like + // _E9_9F_B3_E4_B9_90 which is pretty meaningless. + // https://github.com/google/blockly/issues/1654 + name = encodeURI(name.replace(/ /g, '_')).replace(/[^,\w]/g, '_'); + // Most languages don't allow names with leading numbers. + if ('0123456789'.indexOf(name[0]) != -1) { + name = 'my_' + name; + } + } + return name; + } +} + +/** + * Constant to separate developer variable names from user-defined variable + * names when running generators. + * A developer variable will be declared as a global in the generated code, but + * will never be shown to the user in the workspace or stored in the variable + * map. + */ +Names.DEVELOPER_VARIABLE_TYPE = 'DEVELOPER_VARIABLE'; + +export default Names; \ No newline at end of file diff --git a/mixly/boards/default_src/python/others/procedures.js b/mixly/boards/default_src/python/others/procedures.js new file mode 100644 index 00000000..c8791f2e --- /dev/null +++ b/mixly/boards/default_src/python/others/procedures.js @@ -0,0 +1,327 @@ +/** + * @license + * Copyright 2012 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Utility functions for handling procedures. + * @author fraser@google.com (Neil Fraser) + */ +import * as Blockly from 'blockly/core'; + +const Procedures = {}; + +/** + * Constant to separate procedure names from variables and generated functions + * when running generators. + * @deprecated Use Blockly.PROCEDURE_CATEGORY_NAME + */ +Procedures.NAME_TYPE = Blockly.PROCEDURE_CATEGORY_NAME; + +/** + * Find all user-created procedure definitions in a workspace. + * @param {!Blockly.Workspace} root Root workspace. + * @return {!Array.>} Pair of arrays, the + * first contains procedures without return variables, the second with. + * Each procedure is defined by a three-element list of name, parameter + * list, and return value boolean. + */ +Procedures.allProcedures = function (root) { + var blocks = root.getAllBlocks(false); + var proceduresReturn = []; + var proceduresNoReturn = []; + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].getProcedureDef) { + var tuple = blocks[i].getProcedureDef(); + if (tuple) { + if (tuple[2]) { + proceduresReturn.push(tuple); + } else { + proceduresNoReturn.push(tuple); + } + } + } + } + proceduresNoReturn.sort(Procedures.procTupleComparator_); + proceduresReturn.sort(Procedures.procTupleComparator_); + return [proceduresNoReturn, proceduresReturn]; +}; + +/** + * Comparison function for case-insensitive sorting of the first element of + * a tuple. + * @param {!Array} ta First tuple. + * @param {!Array} tb Second tuple. + * @return {number} -1, 0, or 1 to signify greater than, equality, or less than. + * @private + */ +Procedures.procTupleComparator_ = function (ta, tb) { + return ta[0].toLowerCase().localeCompare(tb[0].toLowerCase()); +}; + +/** + * Ensure two identically-named procedures don't exist. + * Take the proposed procedure name, and return a legal name i.e. one that + * is not empty and doesn't collide with other procedures. + * @param {string} name Proposed procedure name. + * @param {!Blockly.Block} block Block to disambiguate. + * @return {string} Non-colliding name. + */ +Procedures.findLegalName = function (name, block) { + if (block.isInFlyout) { + // Flyouts can have multiple procedures called 'do something'. + return name; + } + name = name || Blockly.Msg['UNNAMED_KEY'] || 'unnamed'; + while (!Procedures.isLegalName_(name, block.workspace, block)) { + // Collision with another procedure. + var r = name.match(/^(.*?)(\d+)$/); + if (!r) { + name += '2'; + } else { + name = r[1] + (parseInt(r[2], 10) + 1); + } + } + return name; +}; + +/** + * Does this procedure have a legal name? Illegal names include names of + * procedures already defined. + * @param {string} name The questionable name. + * @param {!Blockly.Workspace} workspace The workspace to scan for collisions. + * @param {Blockly.Block=} opt_exclude Optional block to exclude from + * comparisons (one doesn't want to collide with oneself). + * @return {boolean} True if the name is legal. + * @private + */ +Procedures.isLegalName_ = function (name, workspace, opt_exclude) { + return !Procedures.isNameUsed(name, workspace, opt_exclude); +}; + +/** + * Return if the given name is already a procedure name. + * @param {string} name The questionable name. + * @param {!Blockly.Workspace} workspace The workspace to scan for collisions. + * @param {Blockly.Block=} opt_exclude Optional block to exclude from + * comparisons (one doesn't want to collide with oneself). + * @return {boolean} True if the name is used, otherwise return false. + */ +Procedures.isNameUsed = function (name, workspace, opt_exclude) { + var blocks = workspace.getAllBlocks(false); + // Iterate through every block and check the name. + for (var i = 0; i < blocks.length; i++) { + if (blocks[i] == opt_exclude) { + continue; + } + if (blocks[i].getProcedureDef) { + var procName = blocks[i].getProcedureDef(); + if (Blockly.Names.equals(procName[0], name)) { + return true; + } + } + } + return false; +}; + +/** + * Rename a procedure. Called by the editable field. + * @param {string} name The proposed new name. + * @return {string} The accepted name. + * @this {Blockly.Field} + */ +Procedures.rename = function (name) { + // Strip leading and trailing whitespace. Beyond this, all names are legal. + name = name.trim(); + + var legalName = Procedures.findLegalName(name, this.getSourceBlock()); + var oldName = this.getValue(); + if (oldName != name && oldName != legalName) { + // Rename any callers. + var blocks = this.getSourceBlock().workspace.getAllBlocks(false); + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].renameProcedure) { + blocks[i].renameProcedure(oldName, legalName); + } + } + } + return legalName; +}; + +/** + * Construct the blocks required by the flyout for the procedure category. + * @param {!Blockly.Workspace} workspace The workspace containing procedures. + * @return {!Array.} Array of XML block elements. + */ +Procedures.flyoutCategory = function (workspace) { + var xmlList = []; + if (Blockly.Blocks['procedures_defnoreturn']) { + // + // do something + // + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'procedures_defnoreturn'); + block.setAttribute('gap', 16); + var nameField = Blockly.utils.xml.createElement('field'); + nameField.setAttribute('name', 'NAME'); + nameField.appendChild(Blockly.utils.xml.createTextNode( + Blockly.Msg['PROCEDURES_DEFNORETURN_PROCEDURE'])); + block.appendChild(nameField); + xmlList.push(block); + } + if (Blockly.Blocks['procedures_defreturn']) { + // + // do something + // + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'procedures_defreturn'); + block.setAttribute('gap', 16); + var nameField = Blockly.utils.xml.createElement('field'); + nameField.setAttribute('name', 'NAME'); + nameField.appendChild(Blockly.utils.xml.createTextNode( + Blockly.Msg['PROCEDURES_DEFRETURN_PROCEDURE'])); + block.appendChild(nameField); + xmlList.push(block); + } + if (Blockly.Blocks['procedures_return']) { + // + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'procedures_return'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + if (Blockly.Blocks['procedures_ifreturn']) { + // + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'procedures_ifreturn'); + block.setAttribute('gap', 16); + xmlList.push(block); + } + if (xmlList.length) { + // Add slightly larger gap between system blocks and user calls. + xmlList[xmlList.length - 1].setAttribute('gap', 24); + } + + function populateProcedures(procedureList, templateName) { + for (var i = 0; i < procedureList.length; i++) { + var name = procedureList[i][0]; + var args = procedureList[i][1]; + // + // + // + // + // + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', templateName); + block.setAttribute('gap', 16); + var mutation = Blockly.utils.xml.createElement('mutation'); + mutation.setAttribute('name', name); + block.appendChild(mutation); + for (var j = 0; j < args.length; j++) { + var arg = Blockly.utils.xml.createElement('arg'); + arg.setAttribute('name', args[j]); + mutation.appendChild(arg); + } + xmlList.push(block); + } + } + + var tuple = Procedures.allProcedures(workspace); + populateProcedures(tuple[0], 'procedures_callnoreturn'); + populateProcedures(tuple[1], 'procedures_callreturn'); + return xmlList; +}; + +/** + * Find all the callers of a named procedure. + * @param {string} name Name of procedure. + * @param {!Blockly.Workspace} workspace The workspace to find callers in. + * @return {!Array.} Array of caller blocks. + */ +Procedures.getCallers = function (name, workspace) { + var callers = []; + var blocks = workspace.getAllBlocks(false); + // Iterate through every block and check the name. + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].getProcedureCall) { + var procName = blocks[i].getProcedureCall(); + // Procedure name may be null if the block is only half-built. + if (procName && Blockly.Names.equals(procName, name)) { + callers.push(blocks[i]); + } + } + } + return callers; +}; + +/** + * When a procedure definition changes its parameters, find and edit all its + * callers. + * @param {!Blockly.Block} defBlock Procedure definition block. + */ +Procedures.mutateCallers = function (defBlock) { + const oldRecordUndo = Blockly.Events.getRecordUndo(); + const procedureBlock = defBlock; + const name = procedureBlock.getProcedureDef()[0]; + const xmlElement = defBlock.mutationToDom(true); + const callers = Blockly.Procedures.getCallers(name, defBlock.workspace); + for (let i = 0, caller; (caller = callers[i]); i++) { + const oldMutationDom = caller.mutationToDom(); + const oldMutation = oldMutationDom && Blockly.utils.xml.domToText(oldMutationDom); + if (caller.domToMutation) { + caller.domToMutation(xmlElement); + } + const newMutationDom = caller.mutationToDom(); + const newMutation = newMutationDom && Blockly.utils.xml.domToText(newMutationDom); + if (oldMutation !== newMutation) { + // Fire a mutation on every caller block. But don't record this as an + // undo action since it is deterministically tied to the procedure's + // definition mutation. + Blockly.Events.setRecordUndo(false); + Blockly.Events.fire( + new (Blockly.Events.get(Blockly.Events.BLOCK_CHANGE))( + caller, + 'mutation', + null, + oldMutation, + newMutation, + ), + ); + Blockly.Events.setRecordUndo(oldRecordUndo); + } + } +}; + +/** + * Find the definition block for the named procedure. + * @param {string} name Name of procedure. + * @param {!Blockly.Workspace} workspace The workspace to search. + * @return {Blockly.Block} The procedure definition block, or null not found. + */ +Procedures.getDefinition = function (name, workspace) { + // Assume that a procedure definition is a top block. + var blocks = workspace.getTopBlocks(false); + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].getProcedureDef) { + var tuple = blocks[i].getProcedureDef(); + if (tuple && Blockly.Names.equals(tuple[0], name)) { + return blocks[i]; + } + } + } + return null; +}; + +export default Procedures; \ No newline at end of file diff --git a/mixly/boards/default_src/python/others/variables.js b/mixly/boards/default_src/python/others/variables.js new file mode 100644 index 00000000..6fbc6c4a --- /dev/null +++ b/mixly/boards/default_src/python/others/variables.js @@ -0,0 +1,248 @@ +/** + * @license + * Visual Blocks Editor + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Utility functions for handling variables. + * @author fraser@google.com (Neil Fraser) + */ + +import * as Blockly from 'blockly/core'; + +const Variables = {}; + +/** + * Category to separate variable names from procedures and generated functions. + */ +Variables.NAME_TYPE = 'VARIABLE'; + +/** + * Find all user-created variables. + * @param {!Blockly.Block|!Blockly.Workspace} root Root block or workspace. + * @return {!Array.} Array of variable names. + */ +Variables.allVariables = function (root) { + var blocks; + if (root.getDescendants) { + // Root is Block. + blocks = root.getDescendants(); + } else if (root.getAllBlocks) { + // Root is Workspace. + blocks = root.getAllBlocks(); + } else { + throw 'Not Block or Workspace: ' + root; + } + var variableHash = Object.create(null); + // Iterate through every block and add each variable to the hash. + for (var x = 0; x < blocks.length; x++) { + var blockVariables = blocks[x].getVars(); + for (var y = 0; y < blockVariables.length; y++) { + var varName = blockVariables[y]; + // Variable name may be null if the block is only half-built. + if (varName) { + variableHash[varName] = varName; + } + } + } + // Flatten the hash into a list. + var variableList = []; + for (var name in variableHash) { + variableList.push(variableHash[name]); + } + return variableList; +}; + +/** + * Find all instances of the specified variable and rename them. + * @param {string} oldName Variable to rename. + * @param {string} newName New variable name. + * @param {!Blockly.Workspace} workspace Workspace rename variables in. + */ +Variables.renameVariable = function (oldName, newName, workspace) { + Blockly.Events.setGroup(true); + var blocks = workspace.getAllBlocks(); + // Iterate through every block. + for (var i = 0; i < blocks.length; i++) { + blocks[i].renameVar(oldName, newName); + } + Blockly.Events.setGroup(false); +}; + +/** + * Construct the blocks required by the flyout for the variable category. + * @param {!Blockly.Workspace} workspace The workspace contianing variables. + * @return {!Array.} Array of XML block elements. + */ +Variables.flyoutCategory = function (workspace) { + var variableList = Variables.allVariables(workspace); + //variableList.sort(goog.string.caseInsensitiveCompare); + // In addition to the user's variables, we also want to display the default + // variable name at the top. We also don't want this duplicated if the + // user has created a variable of the same name. + // alert(variableList) + // goog.array.remove(variableList, Blockly.Msg.VARIABLES_DEFAULT_NAME); + // variableList.unshift(Blockly.Msg.VARIABLES_DEFAULT_NAME); + + var xmlList = []; + + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'variables_global'); + xmlList.push(block); + + if (Blockly.Blocks['variables_set']) { + //增加variables_declare模块 + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'variables_set'); + xmlList.push(block); + }//change tyep + /* + if (Blockly.Blocks['variables_change']) { + //增加variables_declare模块 + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'variables_change'); + xmlList.push(block); + }*/ + if (Blockly.Blocks['variables_change']) { + //增加variables_declare模块 + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'variables_change'); + xmlList.push(block); + } + if (Blockly.Blocks['controls_type']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'controls_type'); + xmlList.push(block); + } + if (Blockly.Blocks['controls_typeLists']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'controls_typeLists'); + xmlList.push(block); + } + if (Blockly.Blocks['lists_zip']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'lists_zip'); + block.setAttribute('inline', 'false'); + var mutation = Blockly.utils.xml.createElement('mutation'); + mutation.setAttribute('items', 2); + block.appendChild(mutation); + for (let i = 0; i < 2; i++) { + let add = Blockly.utils.xml.createElement('value'); + add.setAttribute('name', `ADD${i}`); + // let childBlock = Blockly.utils.xml.createElement('block'); + // childBlock.setAttribute('type', 'list_many_input'); + // let field = Blockly.utils.xml.createElement('field'); + // let value = Blockly.utils.xml.createTextNode('0,1,2,3'); + // field.setAttribute('name', 'CONTENT'); + // field.appendChild(value); + // childBlock.appendChild(field); + // add.appendChild(childBlock); + block.appendChild(add); + } + xmlList.push(block); + } + if (Blockly.Blocks['unpack_iterable_object']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'unpack_iterable_object'); + xmlList.push(block); + } + for (var i = 0; i < variableList.length; i++) { + // alert(variableList) + // if(i==0&& !(Blockly.Python.setups_['variables_set'+''])){ + // continue; + // } + if (Blockly.Blocks['variables_set']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'variables_set'); + if (Blockly.Blocks['variables_get']) { + block.setAttribute('gap', 8); + } + var field = Blockly.utils.xml.createElement('field', null, variableList[i]); + field.setAttribute('name', 'VAR'); + var name = Blockly.utils.xml.createTextNode(variableList[i]); + field.appendChild(name); + block.appendChild(field); + xmlList.push(block); + } + if (Blockly.Blocks['variables_get']) { + var block = Blockly.utils.xml.createElement('block'); + block.setAttribute('type', 'variables_get'); + if (Blockly.Blocks['variables_set']) { + block.setAttribute('gap', 24); + } + var field = Blockly.utils.xml.createElement('field', null, variableList[i]); + field.setAttribute('name', 'VAR'); + var name = Blockly.utils.xml.createTextNode(variableList[i]); + field.appendChild(name); + block.appendChild(field); + xmlList.push(block); + } + } + return xmlList; +}; + +/** +* Return a new variable name that is not yet being used. This will try to +* generate single letter variable names in the range 'i' to 'z' to start with. +* If no unique name is located it will try 'i' to 'z', 'a' to 'h', +* then 'i2' to 'z2' etc. Skip 'l'. + * @param {!Blockly.Workspace} workspace The workspace to be unique in. +* @return {string} New variable name. +*/ +Variables.generateUniqueName = function (workspace) { + var variableList = Variables.allVariables(workspace); + var newName = ''; + if (variableList.length) { + var nameSuffix = 1; + var letters = 'ijkmnopqrstuvwxyzabcdefgh'; // No 'l'. + var letterIndex = 0; + var potName = letters.charAt(letterIndex); + while (!newName) { + var inUse = false; + for (var i = 0; i < variableList.length; i++) { + if (variableList[i] == potName) { + // This potential name is already used. + inUse = true; + break; + } + } + if (inUse) { + // Try the next potential name. + letterIndex++; + if (letterIndex == letters.length) { + // Reached the end of the character sequence so back to 'i'. + // a new suffix. + letterIndex = 0; + nameSuffix++; + } + potName = letters.charAt(letterIndex); + if (nameSuffix > 1) { + potName += nameSuffix; + } + } else { + // We can use the current potential name. + newName = potName; + } + } + } else { + newName = 'i'; + } + return newName; +}; + +export default Variables; \ No newline at end of file diff --git a/mixly/boards/default_src/python/package.json b/mixly/boards/default_src/python/package.json new file mode 100644 index 00000000..092d76be --- /dev/null +++ b/mixly/boards/default_src/python/package.json @@ -0,0 +1,32 @@ +{ + "name": "@mixly/python", + "version": "1.4.0", + "description": "适用于mixly的python模块", + "scripts": { + "build:dev": "webpack --config=webpack.dev.js", + "build:prod": "npm run build:examples & webpack --config=webpack.prod.js", + "build:examples": "node ../../../scripts/build-examples.js -t special", + "build:examples:ob": "node ../../../scripts/build-examples.js -t special --obfuscate", + "publish:board": "npm publish --registry https://registry.npmjs.org/" + }, + "main": "./export.js", + "author": "Mixly Team", + "keywords": [ + "mixly", + "mixly-plugin", + "python" + ], + "homepage": "https://gitee.com/bnu_mixly/mixly3/tree/master/boards/default_src/python", + "bugs": { + "url": "https://gitee.com/bnu_mixly/mixly3/issues" + }, + "repository": { + "type": "git", + "url": "https://gitee.com/bnu_mixly/mixly3.git", + "directory": "default_src/python" + }, + "publishConfig": { + "access": "public" + }, + "license": "Apache 2.0" +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/python_generator.js b/mixly/boards/default_src/python/python_generator.js new file mode 100644 index 00000000..a19bbea1 --- /dev/null +++ b/mixly/boards/default_src/python/python_generator.js @@ -0,0 +1,329 @@ +/* +Overrides for generic Python code generation. +*/ +import * as Blockly from 'blockly/core'; +import Names from './others/names'; + +/** + * Python code generator. + * @type {!Blockly.Generator} + */ +export const Python = new Blockly.Generator('Python'); +Python.INDENT = " "; + +/** + * List of illegal variable names. + * This is not intended to be a security feature. Blockly is 100% client-side, + * so bypassing this list is trivial. This is intended to prevent users from + * accidentally clobbering a built-in object or function. + * @private + */ +Python.addReservedWords( + // import keyword + // print(','.join(sorted(keyword.kwlist))) + // https://docs.python.org/3/reference/lexical_analysis.html#keywords + // https://docs.python.org/2/reference/lexical_analysis.html#keywords + 'False,None,True,and,as,assert,break,class,continue,def,del,elif,else,' + + 'except,exec,finally,for,from,global,if,import,in,is,lambda,nonlocal,not,' + + 'or,pass,print,raise,return,try,while,with,yield,' + + // https://docs.python.org/3/library/constants.html + // https://docs.python.org/2/library/constants.html + 'NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,' + + // >>> print(','.join(sorted(dir(__builtins__)))) + // https://docs.python.org/3/library/functions.html + // https://docs.python.org/2/library/functions.html + 'ArithmeticError,AssertionError,AttributeError,BaseException,' + + 'BlockingIOError,BrokenPipeError,BufferError,BytesWarning,' + + 'ChildProcessError,ConnectionAbortedError,ConnectionError,' + + 'ConnectionRefusedError,ConnectionResetError,DeprecationWarning,EOFError,' + + 'Ellipsis,EnvironmentError,Exception,FileExistsError,FileNotFoundError,' + + 'FloatingPointError,FutureWarning,GeneratorExit,IOError,ImportError,' + + 'ImportWarning,IndentationError,IndexError,InterruptedError,' + + 'IsADirectoryError,KeyError,KeyboardInterrupt,LookupError,MemoryError,' + + 'ModuleNotFoundError,NameError,NotADirectoryError,NotImplemented,' + + 'NotImplementedError,OSError,OverflowError,PendingDeprecationWarning,' + + 'PermissionError,ProcessLookupError,RecursionError,ReferenceError,' + + 'ResourceWarning,RuntimeError,RuntimeWarning,StandardError,' + + 'StopAsyncIteration,StopIteration,SyntaxError,SyntaxWarning,SystemError,' + + 'SystemExit,TabError,TimeoutError,TypeError,UnboundLocalError,' + + 'UnicodeDecodeError,UnicodeEncodeError,UnicodeError,' + + 'UnicodeTranslateError,UnicodeWarning,UserWarning,ValueError,Warning,' + + 'ZeroDivisionError,_,__build_class__,__debug__,__doc__,__import__,' + + '__loader__,__name__,__package__,__spec__,abs,all,any,apply,ascii,' + + 'basestring,bin,bool,buffer,bytearray,bytes,callable,chr,classmethod,cmp,' + + 'coerce,compile,complex,copyright,credits,delattr,dict,dir,divmod,' + + 'enumerate,eval,exec,execfile,exit,file,filter,float,format,frozenset,' + + 'getattr,globals,hasattr,hash,help,hex,id,input,int,intern,isinstance,' + + 'issubclass,iter,len,license,list,locals,long,map,max,memoryview,min,' + + 'next,object,oct,open,ord,pow,print,property,quit,range,raw_input,reduce,' + + 'reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,' + + 'sum,super,tuple,type,unichr,unicode,vars,xrange,zip' +); + +/** + * Order of operation ENUMs. + * http://docs.python.org/reference/expressions.html#summary + */ +Python.ORDER_ATOMIC = 0; // 0 "" ... +Python.ORDER_COLLECTION = 1; // tuples, lists, dictionaries +Python.ORDER_STRING_CONVERSION = 1; // `expression...` +Python.ORDER_UNARY_POSTFIX = 1; // expr++ expr-- () [] . +Python.ORDER_UNARY_PREFIX = 2; // -expr !expr ~expr ++expr --expr +Python.ORDER_MEMBER = 2.1; // . [] +Python.ORDER_FUNCTION_CALL = 2.2; // () +Python.ORDER_EXPONENTIATION = 3; // ** +Python.ORDER_UNARY_SIGN = 4; // + - +Python.ORDER_BITWISE_NOT = 4; // ~ +Python.ORDER_MULTIPLICATIVE = 5; // * / // % +Python.ORDER_ADDITIVE = 6; // + - +Python.ORDER_BITWISE_SHIFT = 7; // << >> +Python.ORDER_BITWISE_AND = 8; // & +Python.ORDER_BITWISE_XOR = 9; // ^ +Python.ORDER_BITWISE_OR = 10; // | +Python.ORDER_RELATIONAL = 11; // in, not in, is, is not, +// <, <=, >, >=, <>, !=, == +Python.ORDER_EQUALITY = 11; // == != === !== +Python.ORDER_LOGICAL_NOT = 12; // not +Python.ORDER_LOGICAL_AND = 13; // and +Python.ORDER_LOGICAL_OR = 14; // or +Python.ORDER_ASSIGNMENT = 14; // = *= /= ~/= %= += -= <<= >>= &= ^= |= +Python.ORDER_CONDITIONAL = 15; // if else +Python.ORDER_LAMBDA = 16; // lambda +Python.ORDER_NONE = 99; // (...) + +/** + * List of outer-inner pairings that do NOT require parentheses. + * @type {!Array.>} + */ +Python.ORDER_OVERRIDES = [ + // (foo()).bar -> foo().bar + // (foo())[0] -> foo()[0] + [Python.ORDER_FUNCTION_CALL, Python.ORDER_MEMBER], + // (foo())() -> foo()() + [Python.ORDER_FUNCTION_CALL, Python.ORDER_FUNCTION_CALL], + // (foo.bar).baz -> foo.bar.baz + // (foo.bar)[0] -> foo.bar[0] + // (foo[0]).bar -> foo[0].bar + // (foo[0])[1] -> foo[0][1] + [Python.ORDER_MEMBER, Python.ORDER_MEMBER], + // (foo.bar)() -> foo.bar() + // (foo[0])() -> foo[0]() + [Python.ORDER_MEMBER, Python.ORDER_FUNCTION_CALL], + + // not (not foo) -> not not foo + // [Python.ORDER_LOGICAL_NOT, Python.ORDER_LOGICAL_NOT], + // a and (b and c) -> a and b and c + // [Python.ORDER_LOGICAL_AND, Python.ORDER_LOGICAL_AND], + // a or (b or c) -> a or b or c + // [Python.ORDER_LOGICAL_OR, Python.ORDER_LOGICAL_OR] +]; + +Python.init = function () { + /** + * Empty loops or conditionals are not allowed in Python. + */ + Python.PASS = this.INDENT + 'pass\n'; + // Create a dictionary of definitions to be printed before the code. + Python.definitions_ = Object.create(null); + // Create a dictionary mapping desired function names in definitions_ + // to actual function names (to avoid collisions with user functions). + Python.functionNames_ = Object.create(null); + Python.setups_ = Object.create(null); + Python.loops_ = Object.create(null); + Python.codeEnd_ = Object.create(null); + + if (!Python.variableDB_) { + Python.variableDB_ = new Names(Python.RESERVED_WORDS_); + } else { + Python.variableDB_.reset(); + } +} + +Python.finish = function (code) { + // Convert the definitions dictionary into a list. + if (code !== "") { + code = code.replace(/\n/g, '\n'); + code = code.replace(/\n\s+$/, '\n'); + } + var imports = []; + var definitions_var = []; //变量定义 + var definitions_fun = []; //函数定义 + for (var name in this.definitions_) { + var def = this.definitions_[name]; + if (name.indexOf('import') === 0) { + imports.push(def); + } else if (name.indexOf('var_declare') === 0) { + definitions_var.push(def); + } else { + definitions_fun.push(def); + } + } + if (imports.length) { + imports.push('\n\n'); + } + if (definitions_var.length) { + definitions_var.push('\n\n'); + } + if (definitions_fun.length) { + definitions_fun.push('\n\n'); + } + var functions = []; + for (var name in Python.functions_) { + functions.push(Python.functions_[name]); + } + if (functions.length) { + functions.push('\n\n'); + } + var setups = []; + for (var name in Python.setups_) { + setups.push(Python.setups_[name]); + } + if (setups.length) { + setups.push('\n\n'); + } + var loops = []; + for (var name in Python.loops_) { + loops.push(Python.loops_[name]); + } + var codeEnd = []; + for (var name in Python.codeEnd_) { + codeEnd.push(Python.codeEnd_[name]); + } + if (codeEnd.length !== 0) { + codeEnd.push('\n'); + } + if (loops.length > 0) { + return imports.join('\n') + definitions_var.join('\n') + definitions_fun.join('\n') + + functions.join('\n') + setups.join('') + code + 'while True:\n' + loops.join('') + codeEnd.join('\n'); + } + return imports.join('\n') + definitions_var.join('\n') + definitions_fun.join('\n') + + functions.join('\n') + setups.join('') + code + codeEnd.join('\n'); +} + + +/** + * Naked values are top-level blocks with outputs that aren't plugged into + * anything. + * @param {string} line Line of generated code. + * @return {string} Legal line of code. + */ +Python.scrubNakedValue = function (line) { + return line + '\n'; +} + +/** + * Encode a string as a properly escaped Python string, complete with quotes. + * @param {string} string Text to encode. + * @return {string} Python string. + * @private + */ +Python.quote_ = function (string) { + // Can't use goog.string.quote since % must also be escaped. + // string = string.replace(/\\/g, '\\\\') + // .replace(/\n/g, '\\\n'); + + // Follow the CPython behaviour of repr() for a non-byte string. + var quote = '\''; + if (string.indexOf('\'') !== -1) { + if (string.indexOf('"') === -1) { + quote = '"'; + } else { + string = string.replace(/'/g, '\\\''); + } + } + return quote + string + quote; +} + +/** + * Encode a string as a properly escaped multiline Python string, complete + * with quotes. + * @param {string} string Text to encode. + * @return {string} Python string. + * @private + */ +Python.multiline_quote_ = function (string) { + // Can't use goog.string.quote since % must also be escaped. + string = string.replace(/'''/g, '\\\'\\\'\\\''); + return '\'\'\'' + string + '\'\'\''; +} + +/** + * Common tasks for generating Python from blocks. + * Handles comments for the specified block and any connected value blocks. + * Calls any statements following this block. + * @param {!Blockly.Block} block The current block. + * @param {string} code The Python code created for this block. + * @param {boolean=} opt_thisOnly True to generate code for only this statement. + * @return {string} Python code with comments and subsequent blocks added. + * @private + */ +Python.scrub_ = function (block, code, opt_thisOnly) { + var commentCode = ''; + // Only collect comments for blocks that aren't inline. + if (!block.outputConnection || !block.outputConnection.targetConnection) { + // Collect comment for this block. + var comment = block.getCommentText(); + if (comment) { + comment = Blockly.utils.string.wrap(comment, + Python.COMMENT_WRAP - 3); + commentCode += Python.prefixLines(comment + '\n', '# '); + } + // Collect comments for all value arguments. + // Don't collect comments for nested statements. + for (var i = 0; i < block.inputList.length; i++) { + if (block.inputList[i].type == Blockly.INPUT_VALUE) { + var childBlock = block.inputList[i].connection.targetBlock(); + if (childBlock) { + var comment = Python.allNestedComments(childBlock); + if (comment) { + commentCode += Python.prefixLines(comment, '# '); + } + } + } + } + } + var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); + var nextCode = opt_thisOnly ? '' : Python.blockToCode(nextBlock); + return commentCode + code + nextCode; +} + +/** + * Gets a property and adjusts the value, taking into account indexing, and + * casts to an integer. + * @param {!Blockly.Block} block The block. + * @param {string} atId The property ID of the element to get. + * @param {number=} opt_delta Value to add. + * @param {boolean=} opt_negate Whether to negate the value. + * @return {string|number} + */ +Python.getAdjustedInt = function (block, atId, opt_delta, opt_negate) { + var delta = opt_delta || 0; + if (block.workspace.options.oneBasedIndex) { + delta--; + } + var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; + var atOrder = delta ? Python.ORDER_ADDITIVE : + Python.ORDER_NONE; + var at = Python.valueToCode(block, atId, atOrder) || defaultAtIndex; + + if (Blockly.isNumber(at)) { + // If the index is a naked number, adjust it right now. + at = parseInt(at, 10) + delta; + if (opt_negate) { + at = -at; + } + } else { + // If the index is dynamic, adjust it in code. + if (delta > 0) { + at = 'int(' + at + ' + ' + delta + ')'; + } else if (delta < 0) { + at = 'int(' + at + ' - ' + -delta + ')'; + } else { + at = 'int(' + at + ')'; + } + if (opt_negate) { + at = '-' + at; + } + } + return at; +} \ No newline at end of file diff --git a/mixly/boards/default_src/python/template.xml b/mixly/boards/default_src/python/template.xml new file mode 100644 index 00000000..e69de29b diff --git a/mixly/boards/default_src/python/webpack.dev.js b/mixly/boards/default_src/python/webpack.dev.js new file mode 100644 index 00000000..54e4088a --- /dev/null +++ b/mixly/boards/default_src/python/webpack.dev.js @@ -0,0 +1,21 @@ +const path = require("path"); +const common = require("../../../webpack.common"); +const { merge } = require("webpack-merge"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const ESLintPlugin = require('eslint-webpack-plugin'); + +module.exports = merge(common, { + mode: "development", + devtool: 'source-map', + plugins: [ + new ESLintPlugin({ + context: process.cwd(), + }), + new HtmlWebpackPlugin({ + inject: false, + template: path.resolve(process.cwd(), 'template.xml'), + filename: 'index.xml', + minify: false + }), + ] +}); \ No newline at end of file diff --git a/mixly/boards/default_src/python/webpack.prod.js b/mixly/boards/default_src/python/webpack.prod.js new file mode 100644 index 00000000..45773239 --- /dev/null +++ b/mixly/boards/default_src/python/webpack.prod.js @@ -0,0 +1,27 @@ +const path = require("path"); +const common = require("../../../webpack.common"); +const { merge } = require("webpack-merge"); +const TerserPlugin = require("terser-webpack-plugin"); +var HtmlWebpackPlugin = require("html-webpack-plugin"); + +module.exports = merge(common, { + mode: "production", + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + extractComments: false, + }), + new HtmlWebpackPlugin({ + inject: false, + template: path.resolve(process.cwd(), 'template.xml'), + filename: 'index.xml', + minify: { + removeAttributeQuotes: true, + collapseWhitespace: true, + removeComments: true, + } + }) + ] + } +}); \ No newline at end of file