Aily BlocklyのABSでブロックの接続形式や引数順、値・変数の書き方を確認し、条件分岐やループを含むブロックコードを記述するための構文リファレンスです。
- ABSの引数順を確認したいとき
- 条件分岐やループを記述したいとき
- Blocklyコードの構文を調べたいとき
ArduinoやESP32のライブラリをAily Blockly向けに変換するため、公開APIの分析からブロック定義、コード生成、ボード対応、パッケージ構成までの手順を確認できます。
Complete guide for converting Arduino/ESP32 hardware libraries into Aily Blockly compatible format. Covers the full workflow: source analysis, block.json design, generator.js implementation, toolbox.json configuration, bus initialization (Serial/I2C/SPI), board adaptation, and packaging.
実行スコア 未検証
インストール方法を見るArduinoやESP32向けのハードウェアライブラリを、Aily Blocklyで使えるライブラリ形式に変換する手順を確認できます。ヘッダーファイルから公開APIを分類し、block.jsonでブロックを設計し、generator.jsでコード生成を実装、toolbox.jsonやpackage.jsonを整える流れを扱います。Serial、I2C、SPIの初期化、変数の扱い、ボード設定への適応、元ライブラリのソース配置、README作成についても具体例があります。完成後のインストールやテストを案内する手順も含まれています。
既存のArduinoライブラリをビジュアルブロックから操作したいときや、センサー、通信機器などのライブラリをAily Blocklyに移植したいときに向いています。ブロック定義や生成コードの設計方針を一通り確認できます。
ライブラリファイルはプロジェクト内の<library-name>/に作成し、node_modules/には作成しません。README作成時には指定された規約ファイルを参照します。
この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。
インストールする前に、エージェントに与えられる指示の中身を確認できます。
A systematic guide for converting Arduino libraries into Aily Blockly libraries, based on real conversion cases (ArduinoJson, OneButton, MQTT/PubSubClient, DHT, INA219, VL53L0X, etc.).
project with action="create" to create one, then continue with the new project path.All library files MUST be created in <projectPath>/<library-name>/, NOT in node_modules/.
<projectPath>/lib-grove_motor/block.json<projectPath>/node_modules/@aily-project/lib-grove_motor/block.jsonThe node_modules/ directory is managed by npm and is write-protected.
After creating the library locally, install it with: npm install ./<library-name>
If a file write operation returns a path/permission error, check your target path — you are likely
writing to node_modules/ instead of <projectPath>/<library-name>/. Fix the path and retry.
Do NOT attempt to bypass by using terminal commands (mkdir, echo, Out-File, etc.) to write into protected directories.
Source Analysis: Analyze the Arduino library header files to identify public APIs. Classify by operation type: initialization, connection, communication, status, maintenance, quick operations.
Block Design: Design user-friendly blocks following block type mapping rules (see Section "Block Design Rules" below).
Create Library Files in <projectPath>/<library-name>/:
block.json — Block definitionsgenerator.js — Code generatortoolbox.json — Toolbox configurationpackage.json — Library metadataCopy Source Files: Use run_terminal to copy the Arduino source:
src/ folder exists → copy to <projectPath>/<library-name>/src/<library-name>/src/ folder → copy .c, .cpp, .h, .hpp files to <projectPath>/<library-name>/src/<library-name>/Write README.md: First read Blockly_Library_README_Conventions.md (fetch from https://blockly.diandeng.tech/files/Blockly_Library_README_Conventions.md), then follow its format.
Post-conversion: Ask the user if they need help with:
npm i <library-path> (must specify the local library path)library-name/
├─ block.json // Block definitions
├─ generator.js // Code generator
├─ toolbox.json // Toolbox configuration
├─ package.json // Library metadata
├─ README.md // Human-readable documentation
├─ README_AI.md // LLM-readable documentation
└─ src/
└─ library-name/ // Copied Arduino source files
IMPORTANT: For complete code specification with detailed examples, read the companion file
Blockly_Library_CODE_Conventions.md located in this skill's folder. It covers:
The sections below summarize the critical rules that MUST be followed.
| Arduino Pattern | Block Type | Connection | Field Type |
|---|---|---|---|
| Object creation/init | Statement | prev/next | field_input (user enters new var name) |
| Global object method | Statement | prev/next | No variable field (direct call) |
| Object method call | Statement | prev/next | field_variable (select existing var) |
| Global object query | Value | output | No variable field |
| Quick operation | Statement/Value | standard | No variable field, direct params |
| Event callback | Hat block | No prev/next | field_variable + input_statement |
| Conditional callback | Hybrid | prev/next | input_value + input_statement |
| Status query | Value | output | field_variable |
field_input: For initialization blocks — user enters a NEW variable namefield_variable: For method call blocks — user selects an EXISTING variable (set variableTypes and defaultType)// field_input
const varName = block.getFieldValue('VAR') || 'defaultVar';
// field_variable
const varField = block.getField('VAR');
const varName = varField ? varField.getText() : 'defaultVar';
// Global object — use directly
const serialPort = block.getFieldValue('SERIAL') || 'Serial';
Use these in field_dropdown options — auto-populated at runtime:
| Variable | Usage |
|---|---|
${board.i2c} | I2C interface list (Wire selector) |
${board.digitalPins} | Digital pin list |
${board.analogPins} | Analog pin list |
${board.serialPort} | Serial port list |
${board.serialSpeed} | Baud rate list |
${board.interruptPins} | Interrupt pin list |
${board.interruptMode} | Interrupt mode list |
Register dynamic extensions in generator.js. Always unregister before registering:
if (Blockly.Extensions.isRegistered('ext_name')) {
Blockly.Extensions.unregister('ext_name');
}
Blockly.Extensions.register('ext_name', function() { /* ... */ });
All injection methods take (tag, code) and auto-deduplicate by tag.
#include <Lib.h> // addLibrary(tag, code)
#define MACRO val // addMacro(tag, code)
Type globalVar; // addVariable(tag, code)
MyClass obj; // addObject(tag, code)
void helper() {} // addFunction(tag, code, isGlobal?)
void setup() {
Serial.begin(9600); // addSetupBegin — bus-level init ONLY
sensor.begin(); // addSetup — device/sensor init
attachCb(handler); // addSetupEnd — callbacks, depends on prior init
}
void loop() {
btn.tick(); // addLoopBegin — polling/tick calls
// [user blocks here]
}
Serial — Always use ensureSerialBegin(), NEVER write Serial.begin() directly:
// ✅ Correct
ensureSerialBegin('Serial', generator); // default 9600
ensureSerialBegin('Serial', generator, 115200); // custom baud
ensureSerialBegin(serialPort, generator, baud); // dynamic
// ❌ FORBIDDEN
generator.addSetupBegin('serial_begin', 'Serial.begin(9600);');
I2C — Use wire_${wireName}_begin key for deduplication:
const wire = block.getFieldValue('WIRE') || 'Wire';
generator.addLibrary('Wire', '#include <Wire.h>');
const wireBeginKey = `wire_${wire}_begin`;
if (!generator.setupCodes_ || !generator.setupCodes_[wireBeginKey]) {
generator.addSetup(wireBeginKey, wire + '.begin();\n');
}
SPI — Use spi_${spiName}_begin key for deduplication:
const spi = block.getFieldValue('SPI') || 'SPI';
generator.addLibrary('SPI', '#include <SPI.h>');
generator.addSetup(`spi_${spi}_begin`, spi + '.begin();\n');
Initialization blocks with field_input MUST implement a rename listener:
if (!block._varMonitorAttached) {
block._varMonitorAttached = true;
block._varLastName = block.getFieldValue('VAR') || 'defaultVar';
registerVariableToBlockly(block._varLastName, 'VarType');
const varField = block.getField('VAR');
if (varField) {
const orig = varField.onFinishEditing_;
varField.onFinishEditing_ = function(newName) {
if (typeof orig === 'function') orig.call(this, newName);
const ws = block.workspace || Blockly.getMainWorkspace?.();
const oldName = block._varLastName;
if (ws && newName && newName !== oldName) {
renameVariableInBlockly(block, oldName, newName, 'VarType');
block._varLastName = newName;
}
};
}
}
return 'code;\n';return [expr, generator.ORDER_ATOMIC];return ''; (empty string — event-driven, not in main flow)return 'conditional_code;\n'; (returned code runs inside parent callback)// Extract input value (most cases use ORDER_ATOMIC)
const val = generator.valueToCode(block, 'INPUT', generator.ORDER_ATOMIC) || '0';
// Return value block
return [varName + '.read()', generator.ORDER_FUNCTION_CALL];
Access runtime board config via window['boardConfig']:
const boardConfig = window['boardConfig'];
// boardConfig.core — e.g. 'esp32:esp32', 'arduino:avr'
// boardConfig.name — board display name
// boardConfig.i2c — I2C interface list
// boardConfig.digitalPins — digital pin list
NEVER modify window['boardConfig'] directly — use independent storage like window['customXxx'].
All input_value slots MUST have shadow blocks:
{
"kind": "block",
"type": "sensor_read",
"inputs": {
"TIMEOUT": {"shadow": {"type": "math_number", "fields": {"NUM": 1000}}}
}
}
Organize blocks by user cognitive flow using label separators:
{
"kind": "category",
"name": "SensorLib",
"contents": [
{"kind": "label", "text": "Setup"},
{"kind": "block", "type": "sensor_init"},
{"kind": "label", "text": "Read Data"},
{"kind": "block", "type": "sensor_read"}
]
}
{
"name": "@aily-project/lib-libname",
"nickname": "Display Name",
"description": "Brief description (<50 chars)",
"version": "1.0.0",
"compatibility": {
"core": [],
"voltage": [3.3, 5]
},
"keywords": ["aily", "blockly"],
"tested": true,
"url": "original library URL"
}
Board compatibility shorthand:
"core": [] (empty array = all boards)"core": ["esp32:esp32"]"core": ["arduino:avr", "arduino:megaavr"]"core": ["esp32:esp32", "esp8266:esp8266", "renesas_uno:unor4wifi"]| ❌ Wrong | ✅ Correct |
|---|---|
Write Serial.begin() directly | Use ensureSerialBegin(port, generator) |
Hardcoded Wire key 'WIRE_BEGIN' | Use wire_${wireName}_begin formatted key |
Modify window['boardConfig'] | Use window['customXxx'] for custom storage |
addSetupBegin for sensor init | addSetupBegin is bus-only; use addSetup for sensors |
No shadow blocks for input_value | Always configure shadow blocks in toolbox.json |
| Extension register without unregister | Always unregister() before register() |
addFunction without 3rd param | Pass true when helper function must be globally visible |
Skip ensureSerialBegin in quick ops | Quick operations using Serial.println need it too |
input_value have shadow blocks in toolbox.jsonensureSerialBegin()wire_${wire}_begin key deduplicationspi_${spi}_begin key deduplicationaddSetupBegin only used for bus-level initializationwindow['boardConfig']field_input blocksまだレビューはありません。使ってみた感想をお寄せください。
ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。
まだコメントはありません。最初のコメントを書いてみませんか。
Aily BlocklyのABSでブロックの接続形式や引数順、値・変数の書き方を確認し、条件分岐やループを含むブロックコードを記述するための構文リファレンスです。
BlocklyやABSプログラムの編集で、必要なライブラリ情報を確認し、ワークスペースへの反映と変更に応じた検証を進めます。
新しいBlocklyプロジェクトの候補ボードやライブラリを調べ、配線や検証手順を含む計画を提示して選択を促します。
過去のチャット履歴を検索し、以前の決定やツール実行、作業内容、利用上の工夫を確認できます。必要に応じて履歴の検索用インデックスも再構築します。
会話の要点や未完了の作業、参照すべき資料を一時ディレクトリの引き継ぎ文書にまとめ、次のエージェントが続きから作業できるようにします。
コードベースを読み取り専用で調査し、バグやセキュリティ、性能、テスト、技術的負債などの改善点を優先順位付きで整理して、別の担当者が実行できる計画にまとめます。