mirror of
https://github.com/CopterExpress/clover.git
synced 2026-05-26 11:43:25 +00:00
* Clover Blockly: add first blocks set * Adjust Blockly settings * Fix get_position output type * Add screenshot * Rename readme.md to README.md * Resize screenshot * Add package.xml * Little change * Fixes * Add python_compressed to blockly * Implement some of the Clover blocks in Python * Make Python indentation 4 spaces * Fixes to Python blocks implementation * Implement set_velocity block in Python * Implement wait_arrival block in Python * Fix indentation in Python implementation of blocks * Fix * Fix land_wait template * Set reserved words in Python * Change default frame_id to aruco_map in get_position block * Fix * Move blocks definitions to blocks.js * Get rid of missing favicon error * Simplify navigate * Rearrange layout, add tabs * Generate Python code * Small style change * -console.log * Code style * Use modules * Move modules to the header * Correct order for ROS definitions + generating "backend" code * Fix rangefinder_distance block * simple_offboard: commands to change only yaw and yaw rate * Implement set_yaw block * Start working on Blockly documentation * Implement print block with a topic * Unneeded code * Little fixes * Fix indentation * Fixes * Fix wait_arival, get_distance * Implement running Blockly programs, implement prompt block, fixes * Add land button * Little change * Fix reserved words + little fixes * +x for main.py * Simplify run button * Auto-save and load workspace * Make land button work * Handle exceptions * Minor change * Add help URL for blocks * Fix * Implement arrived block * Mark blockly and highlight.js as linguist-vendored * Add forgotten CMakeLists.txt * Add wait checkbox to set_yaw block * Disable run button when disconnected * Add message and service files * Add some comments * Add tooltip to some blocks * Implement GPIO blocks * Don’t latch print message to prevent duplication * Prevent duplication prompts * Add ROS init code to backend code anyways * Make GPIO blocks color a constant * Minor fix * More correctly update blocks on input value changes * Minor fixes * Remove unneeded readonly attribute * Add marker ID shadow blocks to toolbox * Add lacking reserved words * Fix frame id generation for complex marker id expressions * Consider frame_id in set_yaw block * Shorten ros module import * Implement stop service * Disable and enable run button correctly * Don’t print KeyboardInterrupt exceptions * Put notifications to notifications element * Add 'running' mark * Disable signal in backend python code * Sleep a little bit to let rospy initialize publishers * Remove accidental code * Make ROS namespace and private namespace constants * editorconfig-lint: don’t check Blockly code * Use private namespace constant in Python generator * Implement ~running topic to display current program status more robustly * Make navigate tolerance and sleep time constants * Make set_leds and and set_effect services proxies persistent * Replace a number with constant * Limit ~block topic publishing rate Otherwise messages get queued making the frontend to freeze * Improve internal documentation * Append 'map' to frames list * Return degrees in get_attitude block * Move getting yaw in a separate block * Improve block tooltips * Add some more files to editorconfig-lint excludes * Add get_yaw block to toolbox * Implement get_time block * Implement ~store and ~load services for storing user programs * Set auto_arm only in take_off block * Minor CSS fixes * Make 'Python' tab textarea-like * Implement saving and loading programs * Adjust styles * Retrieve only .xml files in load service * Forgotten code * Documentation on store and load services * Add some examples * Add blocks programming arg to launch file * Update docs * Add package’s dependencies * Add dependency * Add title to select * Fix syntax * Minor fix in docs * Add forgotten roslib.js * Run user program in the same process * Use print function for print block in Python 2 * Add variables example * Fix url * Add functions example * Fix set_servo block * Fix gpio_read block * Update blocks screenshot * Update docs * Update docs * Fix set_effect block * Minor fix in example * Add setpoint block, remove set_velocity from toolbox * Remove unused modules * Unused variable * Add English article skeleton * Clarify backend node link error * Remove unused variable * Update documentation * Fix link to documentation * Add Blockly logo * Update English article * Add Blocks programming link to the main page * Minor change * Add catkin_install_python to CMakeLists.txt * Make navigate tolerance and sleep time configurable * Add minor todo * Add blockly examples directory to editorconfig-lint excludes * Rename main node to clover_blocks * Add a warning to the old blocks programming article * Fix editorconfig-lint exclude
435 lines
15 KiB
JavaScript
435 lines
15 KiB
JavaScript
import {params} from './ros.js';
|
|
|
|
// If any new block imports any library, add that library name here.
|
|
Blockly.Python.addReservedWords('_b,_print');
|
|
Blockly.Python.addReservedWords('rospy,srv,Trigger,get_telemetry,navigate,set_velocity,land');
|
|
Blockly.Python.addReservedWords('navigate_wait,land_wait,wait_arrival,wait_yaw,get_distance');
|
|
Blockly.Python.addReservedWords('pigpio,pi,Range');
|
|
Blockly.Python.addReservedWords('SetLEDEffect,set_effect');
|
|
Blockly.Python.addReservedWords('SetLEDs,LEDState,set_leds');
|
|
|
|
// TODO: parametrize
|
|
const navigate_tolerance = 0.2;
|
|
const sleep_time = 0.2;
|
|
|
|
const IMPORT_SRV = `from clover import srv
|
|
from std_srvs.srv import Trigger`;
|
|
|
|
// TODO: tolerance to parameters
|
|
const NAVIGATE_WAIT = () => `\ndef navigate_wait(x=0, y=0, z=0, speed=0.5, frame_id='body', auto_arm=False):
|
|
res = navigate(x=x, y=y, z=z, yaw=float('nan'), speed=speed, frame_id=frame_id, auto_arm=auto_arm)
|
|
|
|
if not res.success:
|
|
raise Exception(res.message)
|
|
|
|
while not rospy.is_shutdown():
|
|
telem = get_telemetry(frame_id='navigate_target')
|
|
if math.sqrt(telem.x ** 2 + telem.y ** 2 + telem.z ** 2) < ${params.navigate_tolerance}:
|
|
return
|
|
rospy.sleep(${params.sleep_time})\n`;
|
|
|
|
const LAND_WAIT = () => `\ndef land_wait():
|
|
land()
|
|
while get_telemetry().armed:
|
|
rospy.sleep(${params.sleep_time})\n`;
|
|
|
|
// TODO: tolerance to parameters
|
|
const WAIT_YAW = () => `\ndef wait_yaw():
|
|
while not rospy.is_shutdown():
|
|
telem = get_telemetry(frame_id='navigate_target')
|
|
if abs(telem.yaw) < math.radians(20):
|
|
return
|
|
rospy.sleep(${params.sleep_time})\n`;
|
|
|
|
// TODO: tolerance to parameters
|
|
const WAIT_ARRIVAL = () => `\ndef wait_arrival():
|
|
while not rospy.is_shutdown():
|
|
telem = get_telemetry(frame_id='navigate_target')
|
|
if math.sqrt(telem.x ** 2 + telem.y ** 2 + telem.z ** 2) < ${params.navigate_tolerance}:
|
|
return
|
|
rospy.sleep(${params.sleep_time})\n`;
|
|
|
|
// TODO: tolerance to parameters
|
|
const ARRIVED = () => `\ndef arrived():
|
|
telem = get_telemetry(frame_id='navigate_target')
|
|
return math.sqrt(telem.x ** 2 + telem.y ** 2 + telem.z ** 2) < ${params.navigate_tolerance}\n`
|
|
|
|
const GET_DISTANCE = `\ndef get_distance(x, y, z, frame_id):
|
|
telem = get_telemetry(frame_id)
|
|
return math.sqrt((x - telem.x) ** 2 + (y - telem.y) ** 2 + (z - telem.z) ** 2)\n`;
|
|
|
|
var rosDefinitions = {};
|
|
|
|
function generateROSDefinitions() {
|
|
// order for ROS definitions is significant, so generate all ROS definitions as one
|
|
var code = `rospy.init_node('flight')\n\n`;
|
|
if (rosDefinitions.offboard) {
|
|
code += `get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)\n`;
|
|
code += `navigate = rospy.ServiceProxy('navigate', srv.Navigate)\n`;
|
|
if (rosDefinitions.setVelocity) {
|
|
code += `set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)\n`;
|
|
}
|
|
if (rosDefinitions.setAttitude) {
|
|
code += `set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)\n`;
|
|
}
|
|
if (rosDefinitions.setRates) {
|
|
code += `set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)\n`;
|
|
}
|
|
code += `land = rospy.ServiceProxy('land', Trigger)\n`;
|
|
}
|
|
if (rosDefinitions.setEffect) {
|
|
Blockly.Python.definitions_['import_led_effect'] = 'from clover.srv import SetLEDEffect';
|
|
code += `set_effect = rospy.ServiceProxy('led/set_effect', SetLEDEffect, persistent=True)\n`;
|
|
}
|
|
if (rosDefinitions.setLeds) {
|
|
Blockly.Python.definitions_['import_set_led'] = 'from led_msgs.srv import SetLEDs\nfrom led_msgs.msg import LEDState';
|
|
code += `set_leds = rospy.ServiceProxy('led/set_leds', SetLEDs, persistent=True)\n`;
|
|
}
|
|
if (rosDefinitions.navigateWait) {
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
code += NAVIGATE_WAIT();
|
|
}
|
|
if (rosDefinitions.landWait) {
|
|
code += LAND_WAIT();
|
|
}
|
|
if (rosDefinitions.waitArrival) {
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
code += WAIT_ARRIVAL();
|
|
}
|
|
if (rosDefinitions.arrived) {
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
code += ARRIVED();
|
|
}
|
|
if (rosDefinitions.waitYaw) {
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
code += WAIT_YAW();
|
|
}
|
|
if (rosDefinitions.distance) {
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
code += GET_DISTANCE;
|
|
}
|
|
Blockly.Python.definitions_['ros'] = code;
|
|
}
|
|
|
|
function initNode() {
|
|
Blockly.Python.definitions_['import_rospy'] = 'import rospy';
|
|
generateROSDefinitions();
|
|
}
|
|
|
|
function simpleOffboard() {
|
|
rosDefinitions.offboard = true;
|
|
Blockly.Python.definitions_['import_srv'] = IMPORT_SRV;
|
|
initNode();
|
|
}
|
|
|
|
// Adjust indentation
|
|
Blockly.Python.INDENT = ' ';
|
|
|
|
export function generateUserCode(workspace) {
|
|
rosDefinitions = {};
|
|
Blockly.Python.STATEMENT_PREFIX = null;
|
|
return Blockly.Python.workspaceToCode(workspace);
|
|
}
|
|
|
|
export function generateCode(workspace) {
|
|
rosDefinitions = {};
|
|
Blockly.Python.STATEMENT_PREFIX = '_b(%1)\n';
|
|
var code = Blockly.Python.workspaceToCode(workspace);
|
|
return code;
|
|
}
|
|
|
|
function buildFrameId(block) {
|
|
let frame = block.getFieldValue('FRAME_ID').toLowerCase();
|
|
let id = Blockly.Python.valueToCode(block, 'ID', Blockly.Python.ORDER_NONE);
|
|
if (frame == 'aruco') { // aruco marker frame
|
|
if (id.match(/^[0-9]+$/)) { // id is positive integer
|
|
return `'${frame}_${id}'`;
|
|
} else { // something else...
|
|
return `'${frame}_' + str(int(${id}))`;
|
|
}
|
|
} else {
|
|
return `'${frame}'`;
|
|
}
|
|
}
|
|
|
|
Blockly.Python.navigate = function(block) {
|
|
let x = Blockly.Python.valueToCode(block, 'X', Blockly.Python.ORDER_NONE);
|
|
let y = Blockly.Python.valueToCode(block, 'Y', Blockly.Python.ORDER_NONE);
|
|
let z = Blockly.Python.valueToCode(block, 'Z', Blockly.Python.ORDER_NONE);
|
|
let frameId = buildFrameId(block);
|
|
let speed = Blockly.Python.valueToCode(block, 'SPEED', Blockly.Python.ORDER_NONE);
|
|
|
|
let params = [`x=${x}`, `y=${y}`, `z=${z}`, `frame_id=${frameId}`, `speed=${speed}`];
|
|
|
|
simpleOffboard();
|
|
|
|
if (block.getFieldValue('WAIT') == 'TRUE') {
|
|
rosDefinitions.navigateWait = true;
|
|
simpleOffboard();
|
|
|
|
return `navigate_wait(${params.join(', ')})\n`;
|
|
|
|
} else {
|
|
if (frameId != 'body') {
|
|
params.push(`yaw=float('nan')`);
|
|
}
|
|
return `navigate(${params.join(', ')})\n`;
|
|
}
|
|
}
|
|
|
|
Blockly.Python.set_velocity = function(block) {
|
|
let x = Blockly.Python.valueToCode(block, 'X', Blockly.Python.ORDER_NONE);
|
|
let y = Blockly.Python.valueToCode(block, 'Y', Blockly.Python.ORDER_NONE);
|
|
let z = Blockly.Python.valueToCode(block, 'Z', Blockly.Python.ORDER_NONE);
|
|
let frameId = buildFrameId(block);
|
|
|
|
simpleOffboard();
|
|
|
|
if (frameId == `'body'`) {
|
|
return `set_velocity(vx=${x}, vy=${y}, vz=${z}, frame_id=${frameId})\n`;
|
|
} else {
|
|
return `set_velocity(vx=${x}, vy=${y}, vz=${z}, yaw=float('nan'), frame_id=${frameId})\n`;
|
|
}
|
|
}
|
|
|
|
Blockly.Python.take_off = function(block) {
|
|
simpleOffboard();
|
|
|
|
let z = Blockly.Python.valueToCode(block, 'ALT', Blockly.Python.ORDER_NONE);
|
|
|
|
if (block.getFieldValue('WAIT') == 'TRUE') {
|
|
rosDefinitions.navigateWait = true;
|
|
simpleOffboard();
|
|
|
|
return `navigate_wait(z=${z}, frame_id='body', auto_arm=True)\n`;
|
|
} else {
|
|
return `navigate(z=${z}, frame_id='body', auto_arm=True)\n`;
|
|
}
|
|
}
|
|
|
|
Blockly.Python.land = function(block) {
|
|
simpleOffboard();
|
|
|
|
if (block.getFieldValue('WAIT') == 'TRUE') {
|
|
rosDefinitions.landWait = true;
|
|
simpleOffboard();
|
|
|
|
return `land_wait()\n`;
|
|
} else {
|
|
return 'land()\n';
|
|
}
|
|
}
|
|
|
|
Blockly.Python.angle = function(block) {
|
|
// return [block.getFieldValue('ANGLE'), Blockly.Python.ORDER_UNARY_SIGN];
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
return [`math.radians(${block.getFieldValue('ANGLE')})`, Blockly.Python.ORDER_FUNCTION_CALL];
|
|
|
|
}
|
|
|
|
Blockly.Python.set_yaw = function(block) {
|
|
simpleOffboard();
|
|
let yaw = Blockly.Python.valueToCode(block, 'YAW', Blockly.Python.ORDER_NONE);
|
|
let frameId = buildFrameId(block);
|
|
let code = `navigate(x=float('nan'), y=float('nan'), z=float('nan'), yaw=${yaw}, frame_id=${frameId})\n`;
|
|
if (block.getFieldValue('WAIT') == 'TRUE') {
|
|
rosDefinitions.waitYaw = true;
|
|
simpleOffboard();
|
|
code += 'wait_yaw()\n';
|
|
}
|
|
return code;
|
|
}
|
|
|
|
Blockly.Python.wait_arrival = function(block) {
|
|
rosDefinitions.waitArrival = true;
|
|
simpleOffboard();
|
|
return 'wait_arrival()\n';
|
|
}
|
|
|
|
Blockly.Python.get_time = function(block) {
|
|
initNode();
|
|
return ['rospy.get_time()', Blockly.Python.ORDER_FUNCTION_CALL];
|
|
}
|
|
|
|
Blockly.Python.arrived = function(block) {
|
|
rosDefinitions.arrived = true;
|
|
simpleOffboard();
|
|
return ['arrived()', Blockly.Python.ORDER_FUNCTION_CALL];
|
|
}
|
|
|
|
Blockly.Python.wait = function(block) {
|
|
initNode();
|
|
return `rospy.sleep(${Blockly.Python.valueToCode(block, 'TIME', Blockly.Python.ORDER_NONE)})\n`;
|
|
}
|
|
|
|
Blockly.Python.setpoint = function(block) {
|
|
var type = block.getFieldValue('TYPE');
|
|
let frameId = buildFrameId(block);
|
|
let vx = Blockly.Python.valueToCode(block, 'VX', Blockly.Python.ORDER_NONE);
|
|
let vy = Blockly.Python.valueToCode(block, 'VY', Blockly.Python.ORDER_NONE);
|
|
let vz = Blockly.Python.valueToCode(block, 'VZ', Blockly.Python.ORDER_NONE);
|
|
let yaw = Blockly.Python.valueToCode(block, 'YAW', Blockly.Python.ORDER_NONE);
|
|
let pitch = Blockly.Python.valueToCode(block, 'PITCH', Blockly.Python.ORDER_NONE);
|
|
let roll = Blockly.Python.valueToCode(block, 'ROLL', Blockly.Python.ORDER_NONE);
|
|
let thrust = Blockly.Python.valueToCode(block, 'THRUST', Blockly.Python.ORDER_NONE);
|
|
|
|
if (type == 'VELOCITY') {
|
|
rosDefinitions.setVelocity = true;
|
|
simpleOffboard();
|
|
return `set_velocity(vx=${vx}, vy=${vy}, vz=${vz}, frame_id=${frameId}, yaw=float('nan'))\n`;
|
|
} else if (type == 'ATTITUDE') {
|
|
rosDefinitions.setAttitude = true;
|
|
simpleOffboard();
|
|
return `set_attitude(pitch=${pitch}, roll=${roll}, yaw=${yaw}, thrust=${thrust}, frame_id=${frameId})\n`;
|
|
} else if (type == 'RATES') {
|
|
rosDefinitions.setRates = true;
|
|
simpleOffboard();
|
|
return `set_rate(pitch=${pitch}, roll=${roll}, yaw=${yaw}, thrust=${thrust})\n`;
|
|
}
|
|
}
|
|
|
|
Blockly.Python.get_position = function(block) {
|
|
simpleOffboard();
|
|
let frameId = buildFrameId(block);
|
|
var code = `get_telemetry(${frameId}).${block.getFieldValue('FIELD').toLowerCase()}`;
|
|
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
|
|
}
|
|
|
|
Blockly.Python.get_yaw = function(block) {
|
|
simpleOffboard();
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
let frameId = buildFrameId(block);
|
|
var code = `math.degrees(get_telemetry(${frameId}).yaw)`;
|
|
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
|
|
}
|
|
|
|
Blockly.Python.get_attitude = function(block) {
|
|
simpleOffboard();
|
|
Blockly.Python.definitions_['import_math'] = 'import math';
|
|
var code = `math.degrees(get_telemetry().${block.getFieldValue('FIELD').toLowerCase()})`;
|
|
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
|
|
}
|
|
|
|
Blockly.Python.distance = function(block) {
|
|
rosDefinitions.distance = true;
|
|
simpleOffboard();
|
|
|
|
let x = Blockly.Python.valueToCode(block, 'X', Blockly.Python.ORDER_NONE);
|
|
let y = Blockly.Python.valueToCode(block, 'Y', Blockly.Python.ORDER_NONE);
|
|
let z = Blockly.Python.valueToCode(block, 'Z', Blockly.Python.ORDER_NONE);
|
|
let frameId = buildFrameId(block);
|
|
|
|
return [`get_distance(${x}, ${y}, ${z}, ${frameId})`, Blockly.Python.ORDER_FUNCTION_CALL]
|
|
}
|
|
|
|
Blockly.Python.rangefinder_distance = function(block) {
|
|
initNode();
|
|
Blockly.Python.definitions_['import_range'] = 'from sensor_msgs.msg import Range';
|
|
return [`rospy.wait_for_message('rangefinder/range', Range).range`, Blockly.Python.ORDER_FUNCTION_CALL]
|
|
}
|
|
|
|
Blockly.Python.mode = function(block) {
|
|
simpleOffboard();
|
|
return [`get_telemetry().mode`, Blockly.Python.ORDER_FUNCTION_CALL]
|
|
}
|
|
|
|
Blockly.Python.armed = function(block) {
|
|
simpleOffboard();
|
|
return [`get_telemetry().armed`, Blockly.Python.ORDER_FUNCTION_CALL]
|
|
}
|
|
|
|
Blockly.Python.voltage = function(block) {
|
|
simpleOffboard();
|
|
var code = `get_telemetry().${block.getFieldValue('TYPE').toLowerCase()}`;
|
|
return [code, Blockly.Python.ORDER_FUNCTION_CALL];
|
|
}
|
|
|
|
function parseColor(color) {
|
|
return {
|
|
r: parseInt(color.substr(2, 2), 16),
|
|
g: parseInt(color.substr(4, 2), 16),
|
|
b: parseInt(color.substr(6, 2), 16)
|
|
}
|
|
}
|
|
|
|
const PARSE_COLOR = `def ${Blockly.Python.FUNCTION_NAME_PLACEHOLDER_}(color):
|
|
return {'r': int(color[1:3], 16), 'g': int(color[3:5], 16), 'b': int(color[5:7], 16)}`;
|
|
|
|
// TODO: weird code with colour_rgb block
|
|
Blockly.Python.set_effect = function(block) {
|
|
rosDefinitions.setEffect = true;
|
|
initNode();
|
|
|
|
var effect = block.getFieldValue('EFFECT').toLowerCase();
|
|
|
|
if (effect == 'rainbow' || effect == 'rainbow_fill') {
|
|
return `set_effect(effect='${effect}')\n`;
|
|
} else {
|
|
let colorCode = Blockly.Python.valueToCode(block, 'COLOR', Blockly.Python.ORDER_NONE);
|
|
|
|
if (/^'(.*)'$/.test(colorCode)) { // is simple string
|
|
let color = parseColor(colorCode);
|
|
return `set_effect(effect='${effect}', r=${color.r}, g=${color.g}, b=${color.b})\n`;
|
|
} else {
|
|
let parseColor = Blockly.Python.provideFunction_('parse_color', [PARSE_COLOR]);
|
|
return `set_effect(effect='${effect}', **${parseColor}(${colorCode}))\n`;
|
|
}
|
|
}
|
|
}
|
|
|
|
Blockly.Python.set_led = function(block) {
|
|
rosDefinitions.setLeds = true;
|
|
initNode();
|
|
|
|
var index = Blockly.Python.valueToCode(block, 'INDEX', Blockly.Python.ORDER_NONE);
|
|
var colorCode = Blockly.Python.valueToCode(block, 'COLOR', Blockly.Python.ORDER_NONE);
|
|
|
|
if (/^'(.*)'$/.test(colorCode)) { // is simple string
|
|
let color = parseColor(colorCode);
|
|
return `set_leds([LEDState(index=${index}, r=${color.r}, g=${color.g}, b=${color.b})])\n`;
|
|
} else {
|
|
let parseColor = Blockly.Python.provideFunction_('parse_color', [PARSE_COLOR]);
|
|
return `set_leds([LEDState(index=${index}, **${parseColor}(${colorCode})])\n`;
|
|
}
|
|
}
|
|
|
|
function pigpio() {
|
|
Blockly.Python.definitions_['import_pigpio'] = 'import pigpio';
|
|
Blockly.Python.definitions_['init_pigpio'] = 'pi = pigpio.pi()';
|
|
}
|
|
|
|
const GPIO_READ = `\ndef gpio_read(pin):
|
|
pi.set_mode(pin, pigpio.INPUT)
|
|
return pi.read(pin)\n`;
|
|
|
|
const GPIO_WRITE = `\ndef gpio_write(pin, level):
|
|
pi.set_mode(pin, pigpio.OUTPUT)
|
|
pi.write(pin, level)\n`;
|
|
|
|
const SET_SERVO = `\ndef set_servo(pin, pwm):
|
|
pi.set_mode(pin, pigpio.OUTPUT)
|
|
pi.set_servo_pulsewidth(pin, pwm)\n`;
|
|
|
|
Blockly.Python.gpio_read = function(block) {
|
|
pigpio();
|
|
Blockly.Python.definitions_['gpio_read'] = GPIO_READ;
|
|
var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_NONE);
|
|
return [`gpio_read(${pin})`, Blockly.Python.ORDER_FUNCTION_CALL];
|
|
}
|
|
|
|
Blockly.Python.gpio_write = function(block) {
|
|
pigpio();
|
|
Blockly.Python.definitions_['gpio_write'] = GPIO_WRITE;
|
|
var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_NONE);
|
|
var level = Blockly.Python.valueToCode(block, 'LEVEL', Blockly.Python.ORDER_NONE);
|
|
return `gpio_write(${pin}, ${level})\n`;
|
|
}
|
|
|
|
Blockly.Python.set_servo = function(block) {
|
|
pigpio();
|
|
Blockly.Python.definitions_['set_servo'] = SET_SERVO;
|
|
var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_NONE);
|
|
var pwm = Blockly.Python.valueToCode(block, 'PWM', Blockly.Python.ORDER_NONE);
|
|
return `set_servo(${pin}, ${pwm})\n`;
|
|
}
|