improved addons
parent
7d19311098
commit
952ea2b721
|
|
@ -0,0 +1,163 @@
|
|||
// ESP32-S3 Robot addon
|
||||
//
|
||||
// Blocks: move(left, right) — set both motors -255..255
|
||||
// distance left — sonar distance in cm (value)
|
||||
// distance right — sonar distance in cm (value)
|
||||
//
|
||||
// ─── CONFIGURE YOUR ROBOT ───────────────────────────────────
|
||||
// Edit the pin numbers below to match your wiring, then re-install
|
||||
// the addon (Addons → Remove "esp32s3-robot-addon" → Install same file again).
|
||||
|
||||
var LEFT_MOTOR_PIN1 = 3;
|
||||
var LEFT_MOTOR_PIN2 = 4;
|
||||
var RIGHT_MOTOR_PIN1 = 5;
|
||||
var RIGHT_MOTOR_PIN2 = 6;
|
||||
var LEFT_SONAR_TRIG = 9;
|
||||
var LEFT_SONAR_ECHO = 8;
|
||||
var RIGHT_SONAR_TRIG = 11;
|
||||
var RIGHT_SONAR_ECHO = 10;
|
||||
|
||||
// ─── Block definitions ───────────────────────────────────────
|
||||
|
||||
api.Blockly.Blocks['robot_move'] = {
|
||||
init() {
|
||||
this.appendValueInput('LEFT')
|
||||
.setCheck('Number')
|
||||
.appendField('move left');
|
||||
this.appendValueInput('RIGHT')
|
||||
.setCheck('Number')
|
||||
.appendField('right');
|
||||
this.setInputsInline(true);
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(45);
|
||||
this.setTooltip('Set left and right motor speed (-255 to 255). DRV8833 on pins 3,4 and 5,6.');
|
||||
},
|
||||
};
|
||||
|
||||
api.Blockly.Blocks['robot_distance_left'] = {
|
||||
init() {
|
||||
this.appendDummyInput()
|
||||
.appendField('distance left (cm)');
|
||||
this.setOutput(true, 'Number');
|
||||
this.setColour(65);
|
||||
this.setTooltip('Left sonar distance in cm (trig=9, echo=8)');
|
||||
},
|
||||
};
|
||||
|
||||
api.Blockly.Blocks['robot_distance_right'] = {
|
||||
init() {
|
||||
this.appendDummyInput()
|
||||
.appendField('distance right (cm)');
|
||||
this.setOutput(true, 'Number');
|
||||
this.setColour(65);
|
||||
this.setTooltip('Right sonar distance in cm (trig=11, echo=10)');
|
||||
},
|
||||
};
|
||||
|
||||
// --- Code generators ---
|
||||
|
||||
var gen = api.pythonGenerator;
|
||||
|
||||
// Generated Python pin constants (from config at top of this file).
|
||||
var ROBOT_PINS = [
|
||||
'# Robot pin configuration',
|
||||
'LEFT_MOTOR_PIN1 = ' + LEFT_MOTOR_PIN1,
|
||||
'LEFT_MOTOR_PIN2 = ' + LEFT_MOTOR_PIN2,
|
||||
'RIGHT_MOTOR_PIN1 = ' + RIGHT_MOTOR_PIN1,
|
||||
'RIGHT_MOTOR_PIN2 = ' + RIGHT_MOTOR_PIN2,
|
||||
'LEFT_SONAR_TRIG = ' + LEFT_SONAR_TRIG,
|
||||
'LEFT_SONAR_ECHO = ' + LEFT_SONAR_ECHO,
|
||||
'RIGHT_SONAR_TRIG = ' + RIGHT_SONAR_TRIG,
|
||||
'RIGHT_SONAR_ECHO = ' + RIGHT_SONAR_ECHO,
|
||||
].join('\n');
|
||||
|
||||
var ROBOT_MOTOR_DEF = [
|
||||
'from machine import Pin, PWM',
|
||||
'_robot_left1 = PWM(Pin(LEFT_MOTOR_PIN1), freq=20000, duty=0)',
|
||||
'_robot_left2 = PWM(Pin(LEFT_MOTOR_PIN2), freq=20000, duty=0)',
|
||||
'_robot_right1 = PWM(Pin(RIGHT_MOTOR_PIN1), freq=20000, duty=0)',
|
||||
'_robot_right2 = PWM(Pin(RIGHT_MOTOR_PIN2), freq=20000, duty=0)',
|
||||
'def _robot_set_motor(pwm1, pwm2, speed):',
|
||||
' speed = max(-255, min(255, int(speed)))',
|
||||
' duty = abs(speed) * 4',
|
||||
' if speed > 0:',
|
||||
' pwm1.duty(duty)',
|
||||
' pwm2.duty(0)',
|
||||
' elif speed < 0:',
|
||||
' pwm1.duty(0)',
|
||||
' pwm2.duty(duty)',
|
||||
' else:',
|
||||
' pwm1.duty(0)',
|
||||
' pwm2.duty(0)',
|
||||
].join('\n');
|
||||
|
||||
var ROBOT_SONAR_DEF = [
|
||||
'def _robot_sonar_cm(trig, echo):',
|
||||
' from machine import Pin, time_pulse_us',
|
||||
' import time',
|
||||
' t = Pin(trig, Pin.OUT)',
|
||||
' e = Pin(echo, Pin.IN)',
|
||||
' t.off()',
|
||||
' time.sleep_us(2)',
|
||||
' t.on()',
|
||||
' time.sleep_us(10)',
|
||||
' t.off()',
|
||||
' d = time_pulse_us(e, 1, 30000)',
|
||||
' return round(d / 58.0, 1) if d >= 0 else -1',
|
||||
].join('\n');
|
||||
|
||||
function addRobotDefs() {
|
||||
gen.definitions_['robot_pins'] = ROBOT_PINS;
|
||||
gen.definitions_['robot_motors'] = ROBOT_MOTOR_DEF;
|
||||
gen.definitions_['robot_sonar'] = ROBOT_SONAR_DEF;
|
||||
}
|
||||
|
||||
gen.forBlock['robot_move'] = function (block) {
|
||||
if (api.getDeviceId() !== 'esp32s3') {
|
||||
return '# Robot move block is for ESP32-S3 robot (DRV8833 on 3,4,5,6)\n';
|
||||
}
|
||||
addRobotDefs();
|
||||
var left = gen.valueToCode(block, 'LEFT', gen.ORDER_NONE) || '0';
|
||||
var right = gen.valueToCode(block, 'RIGHT', gen.ORDER_NONE) || '0';
|
||||
return '_robot_set_motor(_robot_left1, _robot_left2, ' + left + ')\n' +
|
||||
'_robot_set_motor(_robot_right1, _robot_right2, ' + right + ')\n';
|
||||
};
|
||||
|
||||
gen.forBlock['robot_distance_left'] = function (block) {
|
||||
if (api.getDeviceId() !== 'esp32s3') {
|
||||
return ['-1', gen.ORDER_ATOMIC];
|
||||
}
|
||||
addRobotDefs();
|
||||
return ['_robot_sonar_cm(LEFT_SONAR_TRIG, LEFT_SONAR_ECHO)', gen.ORDER_FUNCTION_CALL];
|
||||
};
|
||||
|
||||
gen.forBlock['robot_distance_right'] = function (block) {
|
||||
if (api.getDeviceId() !== 'esp32s3') {
|
||||
return ['-1', gen.ORDER_ATOMIC];
|
||||
}
|
||||
addRobotDefs();
|
||||
return ['_robot_sonar_cm(RIGHT_SONAR_TRIG, RIGHT_SONAR_ECHO)', gen.ORDER_FUNCTION_CALL];
|
||||
};
|
||||
|
||||
// --- Register toolbox category ---
|
||||
|
||||
api.registerCategories([
|
||||
{
|
||||
kind: 'category',
|
||||
name: 'ESP32-S3 Robot',
|
||||
colour: '45',
|
||||
contents: [
|
||||
{
|
||||
kind: 'block',
|
||||
type: 'robot_move',
|
||||
inputs: {
|
||||
LEFT: { shadow: { type: 'math_number', fields: { NUM: 0 } } },
|
||||
RIGHT: { shadow: { type: 'math_number', fields: { NUM: 0 } } },
|
||||
},
|
||||
},
|
||||
{ kind: 'block', type: 'robot_distance_left' },
|
||||
{ kind: 'block', type: 'robot_distance_right' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
export const hidCategory = {
|
||||
kind: 'category',
|
||||
name: 'HID (Keyboard / Mouse / Gamepad)',
|
||||
colour: '330',
|
||||
contents: [
|
||||
// Keyboard
|
||||
{ kind: 'block', type: 'hid_key_press' },
|
||||
{ kind: 'block', type: 'hid_key_down' },
|
||||
{ kind: 'block', type: 'hid_key_up' },
|
||||
{
|
||||
kind: 'block',
|
||||
type: 'hid_keyboard_type',
|
||||
inputs: {
|
||||
TEXT: { shadow: { type: 'text', fields: { TEXT: 'hello' } } },
|
||||
},
|
||||
},
|
||||
// Mouse
|
||||
{
|
||||
kind: 'block',
|
||||
type: 'hid_mouse_move',
|
||||
inputs: {
|
||||
X: { shadow: { type: 'math_number', fields: { NUM: 10 } } },
|
||||
Y: { shadow: { type: 'math_number', fields: { NUM: 0 } } },
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'block',
|
||||
type: 'hid_mouse_click',
|
||||
},
|
||||
{
|
||||
kind: 'block',
|
||||
type: 'hid_mouse_scroll',
|
||||
inputs: {
|
||||
DELTA: { shadow: { type: 'math_number', fields: { NUM: 1 } } },
|
||||
},
|
||||
},
|
||||
// Gamepad
|
||||
{ kind: 'block', type: 'hid_gamepad_button' },
|
||||
{
|
||||
kind: 'block',
|
||||
type: 'hid_gamepad_axis',
|
||||
inputs: {
|
||||
VALUE: { shadow: { type: 'math_number', fields: { NUM: 0 } } },
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
@ -357,6 +357,158 @@ Blockly.Blocks['i2c_readfrom'] = {
|
|||
},
|
||||
};
|
||||
|
||||
// ─── HID (Keyboard / Mouse / Gamepad) ─────────────────────
|
||||
// USB HID key codes (Usage Page 0x07). Value is decimal for generator.
|
||||
const HID_KEY_OPTIONS = [
|
||||
['A', '4'], ['B', '5'], ['C', '6'], ['D', '7'], ['E', '8'], ['F', '9'], ['G', '10'],
|
||||
['H', '11'], ['I', '12'], ['J', '13'], ['K', '14'], ['L', '15'], ['M', '16'], ['N', '17'],
|
||||
['O', '18'], ['P', '19'], ['Q', '20'], ['R', '21'], ['S', '22'], ['T', '23'], ['U', '24'],
|
||||
['V', '25'], ['W', '26'], ['X', '27'], ['Y', '28'], ['Z', '29'],
|
||||
['1', '30'], ['2', '31'], ['3', '32'], ['4', '33'], ['5', '34'],
|
||||
['6', '35'], ['7', '36'], ['8', '37'], ['9', '38'], ['0', '39'],
|
||||
['Enter', '40'], ['Esc', '41'], ['Backspace', '42'], ['Tab', '43'], ['Space', '44'],
|
||||
['-', '45'], ['=', '46'], ['[', '47'], [']', '48'], ['\\', '49'], [';', '51'],
|
||||
["'", '52'], ['`', '53'], [',', '54'], ['.', '55'], ['/', '56'],
|
||||
['F1', '58'], ['F2', '59'], ['F3', '60'], ['F4', '61'], ['F5', '62'],
|
||||
['F6', '63'], ['F7', '64'], ['F8', '65'], ['F9', '66'], ['F10', '67'], ['F11', '68'], ['F12', '69'],
|
||||
];
|
||||
|
||||
Blockly.Blocks['hid_key_press'] = {
|
||||
init() {
|
||||
this.appendDummyInput()
|
||||
.appendField('HID key press')
|
||||
.appendField(new Blockly.FieldDropdown(HID_KEY_OPTIONS), 'KEY');
|
||||
this.appendDummyInput()
|
||||
.appendField('modifier')
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
['none', '0'], ['Ctrl', '1'], ['Shift', '2'], ['Alt', '4'], ['GUI/Win', '8'],
|
||||
['Ctrl+Shift', '3'], ['Ctrl+Alt', '5'], ['Shift+Alt', '6'],
|
||||
]), 'MOD');
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Press and release a key (keyboard HID)');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_key_down'] = {
|
||||
init() {
|
||||
this.appendDummyInput()
|
||||
.appendField('HID key down')
|
||||
.appendField(new Blockly.FieldDropdown(HID_KEY_OPTIONS), 'KEY');
|
||||
this.appendDummyInput()
|
||||
.appendField('modifier')
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
['none', '0'], ['Ctrl', '1'], ['Shift', '2'], ['Alt', '4'], ['GUI/Win', '8'],
|
||||
]), 'MOD');
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Hold key down (keyboard HID)');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_key_up'] = {
|
||||
init() {
|
||||
this.appendDummyInput().appendField('HID key up (release all)');
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Release all keyboard keys');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_keyboard_type'] = {
|
||||
init() {
|
||||
this.appendValueInput('TEXT')
|
||||
.setCheck('String')
|
||||
.appendField('HID type text');
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Type a string as keyboard input (HID)');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_mouse_move'] = {
|
||||
init() {
|
||||
this.appendValueInput('X').setCheck('Number').appendField('HID mouse move X');
|
||||
this.appendValueInput('Y').setCheck('Number').appendField('Y');
|
||||
this.setInputsInline(true);
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Move mouse relative (pixels)');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_mouse_click'] = {
|
||||
init() {
|
||||
this.appendDummyInput()
|
||||
.appendField('HID mouse click')
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
['left', '1'], ['right', '2'], ['middle', '4'],
|
||||
]), 'BUTTON');
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Click mouse button (press and release)');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_mouse_scroll'] = {
|
||||
init() {
|
||||
this.appendValueInput('DELTA')
|
||||
.setCheck('Number')
|
||||
.appendField('HID mouse scroll');
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Scroll wheel (positive = up, negative = down)');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_gamepad_button'] = {
|
||||
init() {
|
||||
this.appendDummyInput()
|
||||
.appendField('HID gamepad button')
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
['1', '0'], ['2', '1'], ['3', '2'], ['4', '3'], ['5', '4'], ['6', '5'],
|
||||
['7', '6'], ['8', '7'], ['9', '8'], ['10', '9'], ['11', '10'], ['12', '11'],
|
||||
['13', '12'], ['14', '13'], ['15', '14'], ['16', '15'],
|
||||
]), 'BTN');
|
||||
this.appendDummyInput()
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
['press', '1'],
|
||||
['release', '0'],
|
||||
]), 'STATE');
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Set gamepad button state (1-16)');
|
||||
},
|
||||
};
|
||||
|
||||
Blockly.Blocks['hid_gamepad_axis'] = {
|
||||
init() {
|
||||
this.appendDummyInput()
|
||||
.appendField('HID gamepad axis')
|
||||
.appendField(new Blockly.FieldDropdown([
|
||||
['left X', '0'], ['left Y', '1'], ['right X', '2'], ['right Y', '3'],
|
||||
['left trigger', '4'], ['right trigger', '5'],
|
||||
]), 'AXIS');
|
||||
this.appendValueInput('VALUE')
|
||||
.setCheck('Number')
|
||||
.appendField('value');
|
||||
this.appendDummyInput().appendField('(-127 to 127)');
|
||||
this.setInputsInline(true);
|
||||
this.setPreviousStatement(true, null);
|
||||
this.setNextStatement(true, null);
|
||||
this.setColour(330);
|
||||
this.setTooltip('Set gamepad axis (-127 to 127, 0 = center)');
|
||||
},
|
||||
};
|
||||
|
||||
// ─── Print ────────────────────────────────────────────────
|
||||
|
||||
Blockly.Blocks['print_text'] = {
|
||||
|
|
|
|||
|
|
@ -452,3 +452,168 @@ pythonGenerator.forBlock['superbit_motor_stop_all'] = function (block) {
|
|||
pythonGenerator.definitions_['superbit_lib'] = SUPERBIT_DEF;
|
||||
return '_superbit_motor_stop_all()\n';
|
||||
};
|
||||
|
||||
// ─── HID (Keyboard / Mouse / Gamepad) ──────────────────────
|
||||
// ESP32-S3 only; requires MicroPython firmware with USB HID support (e.g. TinyUSB).
|
||||
|
||||
const HID_HELPER = `# HID helper (keyboard, mouse, gamepad) - ESP32-S3 USB
|
||||
try:
|
||||
import usb_hid
|
||||
except ImportError:
|
||||
usb_hid = None
|
||||
_hid_kb = None
|
||||
_hid_mouse = None
|
||||
_hid_gamepad = None
|
||||
def _hid_devices():
|
||||
global _hid_kb, _hid_mouse, _hid_gamepad
|
||||
if usb_hid is None or _hid_kb is not None:
|
||||
return
|
||||
for d in usb_hid.devices:
|
||||
if getattr(d, 'usage_page', None) == 0x01 and getattr(d, 'usage', None) == 0x06:
|
||||
_hid_kb = d
|
||||
elif getattr(d, 'usage_page', None) == 0x01 and getattr(d, 'usage', None) == 0x02:
|
||||
_hid_mouse = d
|
||||
elif getattr(d, 'usage_page', None) == 0x01 and getattr(d, 'usage', None) == 0x05:
|
||||
_hid_gamepad = d
|
||||
def _hid_keyboard_report(modifier, key):
|
||||
return bytes([int(modifier) & 0xff, 0, int(key) & 0xff, 0, 0, 0, 0, 0])
|
||||
def _hid_key_press(modifier, key):
|
||||
_hid_devices()
|
||||
if _hid_kb:
|
||||
_hid_kb.send(_hid_keyboard_report(modifier, key))
|
||||
_hid_kb.send(_hid_keyboard_report(0, 0))
|
||||
def _hid_key_down(modifier, key):
|
||||
_hid_devices()
|
||||
if _hid_kb:
|
||||
_hid_kb.send(_hid_keyboard_report(modifier, key))
|
||||
def _hid_key_up():
|
||||
_hid_devices()
|
||||
if _hid_kb:
|
||||
_hid_kb.send(_hid_keyboard_report(0, 0))
|
||||
def _hid_type_string(s):
|
||||
_hid_devices()
|
||||
if not _hid_kb:
|
||||
return
|
||||
for c in s:
|
||||
mod = 0x02 if c.isupper() and c.isalpha() else 0
|
||||
low = c.lower() if c.isalpha() else c
|
||||
key = 0
|
||||
if len(low) == 1 and 'a' <= low <= 'z':
|
||||
key = ord(low) - ord('a') + 4
|
||||
elif '0' <= c <= '9':
|
||||
key = ord(c) - ord('0') + 30
|
||||
elif c == ' ':
|
||||
key = 44
|
||||
elif c == chr(10) or c == chr(13):
|
||||
key = 40
|
||||
if key:
|
||||
_hid_kb.send(_hid_keyboard_report(mod, key))
|
||||
_hid_kb.send(_hid_keyboard_report(0, 0))
|
||||
def _s8(v):
|
||||
return (max(-127, min(127, int(v))) + 128) & 0xff
|
||||
def _hid_mouse_move(dx, dy):
|
||||
_hid_devices()
|
||||
if _hid_mouse:
|
||||
_hid_mouse.send(bytes([0, _s8(dx), _s8(dy), 0]))
|
||||
def _hid_mouse_click(btn):
|
||||
_hid_devices()
|
||||
if _hid_mouse:
|
||||
_hid_mouse.send(bytes([int(btn) & 7, 0, 0, 0]))
|
||||
_hid_mouse.send(bytes([0, 0, 0, 0]))
|
||||
def _hid_mouse_scroll(delta):
|
||||
_hid_devices()
|
||||
if _hid_mouse:
|
||||
_hid_mouse.send(bytes([0, 0, 0, _s8(delta)]))
|
||||
def _hid_gamepad_report(buttons, axes):
|
||||
out = [buttons & 0xff, buttons >> 8]
|
||||
for v in axes:
|
||||
out.append((max(-127, min(127, int(v))) + 128) & 0xff)
|
||||
return bytes(out)
|
||||
_hid_gp_buttons = 0
|
||||
_hid_gp_axes = [0, 0, 0, 0, 0, 0]
|
||||
def _hid_gamepad_button(btn_index, state):
|
||||
global _hid_gp_buttons
|
||||
_hid_devices()
|
||||
if _hid_gamepad:
|
||||
if state:
|
||||
_hid_gp_buttons |= 1 << btn_index
|
||||
else:
|
||||
_hid_gp_buttons &= ~(1 << btn_index)
|
||||
_hid_gamepad.send(_hid_gamepad_report(_hid_gp_buttons, _hid_gp_axes))
|
||||
def _hid_gamepad_axis(axis_index, value):
|
||||
_hid_devices()
|
||||
if _hid_gamepad:
|
||||
_hid_gp_axes[axis_index] = max(-127, min(127, int(value)))
|
||||
_hid_gamepad.send(_hid_gamepad_report(_hid_gp_buttons, _hid_gp_axes))
|
||||
`;
|
||||
|
||||
function hidNotSupported() {
|
||||
return DEVICE() !== 'esp32s3';
|
||||
}
|
||||
|
||||
pythonGenerator.forBlock['hid_key_press'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const key = block.getFieldValue('KEY');
|
||||
const mod = block.getFieldValue('MOD');
|
||||
return `_hid_key_press(${mod}, ${key})\n`;
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_key_down'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const key = block.getFieldValue('KEY');
|
||||
const mod = block.getFieldValue('MOD');
|
||||
return `_hid_key_down(${mod}, ${key})\n`;
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_key_up'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
return '_hid_key_up()\n';
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_keyboard_type'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const text = pythonGenerator.valueToCode(block, 'TEXT', Order.NONE) || "''";
|
||||
return `_hid_type_string(${text})\n`;
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_mouse_move'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const x = pythonGenerator.valueToCode(block, 'X', Order.NONE) || '0';
|
||||
const y = pythonGenerator.valueToCode(block, 'Y', Order.NONE) || '0';
|
||||
return `_hid_mouse_move(${x}, ${y})\n`;
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_mouse_click'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const btn = block.getFieldValue('BUTTON');
|
||||
return `_hid_mouse_click(${btn})\n`;
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_mouse_scroll'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const delta = pythonGenerator.valueToCode(block, 'DELTA', Order.NONE) || '1';
|
||||
return `_hid_mouse_scroll(${delta})\n`;
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_gamepad_button'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const btn = block.getFieldValue('BTN');
|
||||
const state = block.getFieldValue('STATE') === '1';
|
||||
return `_hid_gamepad_button(${btn}, ${state})\n`;
|
||||
};
|
||||
|
||||
pythonGenerator.forBlock['hid_gamepad_axis'] = function (block) {
|
||||
if (hidNotSupported()) return '# HID blocks require ESP32-S3 with USB HID firmware\n';
|
||||
pythonGenerator.definitions_['hid_lib'] = HID_HELPER;
|
||||
const axis = block.getFieldValue('AXIS');
|
||||
const value = pythonGenerator.valueToCode(block, 'VALUE', Order.NONE) || '0';
|
||||
return `_hid_gamepad_axis(${axis}, ${value})\n`;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { i2cCategory } from '../blocks/categories/i2c.js';
|
|||
import { serialPrintCategory } from '../blocks/categories/serialPrint.js';
|
||||
import { soundCategory } from '../blocks/categories/sound.js';
|
||||
import { randomCategory } from '../blocks/categories/random.js';
|
||||
import { hidCategory } from '../blocks/categories/hid.js';
|
||||
|
||||
export const esp32s3 = {
|
||||
id: 'esp32s3',
|
||||
|
|
@ -28,6 +29,7 @@ export const esp32s3 = {
|
|||
wifiCategory,
|
||||
neopixelCategory,
|
||||
i2cCategory,
|
||||
hidCategory,
|
||||
soundCategory(),
|
||||
serialPrintCategory,
|
||||
randomCategory,
|
||||
|
|
|
|||
|
|
@ -8,4 +8,22 @@ export default defineConfig({
|
|||
build: {
|
||||
outDir: 'dist',
|
||||
},
|
||||
optimizeDeps: {
|
||||
// esptool-js uses dynamic import() for chip targets (e.g. esp32s3.js); include them
|
||||
// so Vite pre-bundles them and the runtime fetch resolves.
|
||||
include: [
|
||||
'esptool-js',
|
||||
'esptool-js/lib/targets/esp32.js',
|
||||
'esptool-js/lib/targets/esp32c2.js',
|
||||
'esptool-js/lib/targets/esp32c3.js',
|
||||
'esptool-js/lib/targets/esp32c5.js',
|
||||
'esptool-js/lib/targets/esp32c6.js',
|
||||
'esptool-js/lib/targets/esp32c61.js',
|
||||
'esptool-js/lib/targets/esp32h2.js',
|
||||
'esptool-js/lib/targets/esp32p4.js',
|
||||
'esptool-js/lib/targets/esp32s2.js',
|
||||
'esptool-js/lib/targets/esp32s3.js',
|
||||
'esptool-js/lib/targets/esp8266.js',
|
||||
],
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue