Skip to content

feat: Bluetooth LE blocks #171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions packages/blocks/media/l_bluetooth.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/blocks/src/blocks/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as lists from "./lists";
import * as mesh from "./mesh";
import * as rtc from "./rtc";
import * as texts from "./text";
import * as bluetooth from "./bluetooth";

const blocks = [
...lists.blocks,
Expand All @@ -18,6 +19,7 @@ const blocks = [
...leaphyCommon.blocks,
...mesh.blocks,
...rtc.blocks,
...bluetooth.blocks,
];

export { blocks };
139 changes: 139 additions & 0 deletions packages/blocks/src/blocks/bluetooth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {BlockDefinition} from "blockly/core/blocks";

const blocks: BlockDefinition = [
{
type: "bluetooth_setup",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_SETUP}",
args0: [
{
type: "input_value",
name: "NAME",
check: ["String"],
},
],
previousStatement: null,
nextStatement: null,
},
{
type: "bluetooth_start_leaphy_filtered_scan",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_START_LEAPHY_FILTERED_SCAN}",
previousStatement: null,
nextStatement: null,
},
{
type: "bluetooth_start_name_filtered_scan",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_START_NAME_FILTERED_SCAN}",
args0: [
{
type: "input_value",
name: "NAME",
check: ["String"],
},
],
previousStatement: null,
nextStatement: null,
},
{
type: "bluetooth_stop_scan",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_STOP_SCAN}",
previousStatement: null,
nextStatement: null,
},
{
type: "bluetooth_on_connect",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_ON_CONNECT}",
extensions: ["appendStatementInputStack"],
nextStatement: null,
},
{
type: "bluetooth_on_disconnect",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_ON_DISCONNECT}",
extensions: ["appendStatementInputStack"],
nextStatement: null,
},
{
type: "bluetooth_on_discover",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_ON_DISCOVER}",
extensions: ["appendStatementInputStack"],
nextStatement: null,
},
{
type: "bluetooth_on_characteristic_update",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_CHARACTERISTIC_ON_UPDATE}",
args0: [
{
type: "input_value",
name: "NAME",
check: ["String"],
},
],
extensions: ["appendStatementInputStack"],
nextStatement: null,
},
{
type: "bluetooth_create_binary_characteristic",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_CREATE_BINARY_CHARACTERISTIC}",
args0: [
{
type: "input_value",
name: "NAME",
check: ["String"],
},
{ type: "input_value", name: "INITIAL_VALUE", check: "Boolean" },
],
previousStatement: null,
nextStatement: null,
},
{
type: "bluetooth_create_string_characteristic",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_CREATE_STRING_CHARACTERISTIC}",
args0: [
{
type: "input_value",
name: "NAME",
check: ["String"],
},
{ type: "input_value", name: "INITIAL_VALUE", check: "String" },
],
previousStatement: null,
nextStatement: null,
},
{
type: "bluetooth_read_string_characteristic",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_READ_STRING_CHARACTERISTIC}",
args0: [
{
type: "input_value",
name: "NAME",
check: ["String"],
},
],
output: "String",
},
{
type: "bluetooth_read_bool_characteristic",
style: "bluetooth_blocks",
message0: "%{BKY_LEAPHY_BLUETOOTH_READ_BINARY_CHARACTERISTIC}",
args0: [
{
type: "input_value",
name: "NAME",
check: ["String"],
},
],
output: "Boolean",
},
];

export {blocks};
2 changes: 2 additions & 0 deletions packages/blocks/src/generators/arduino.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ import * as rtc from "./arduino/rtc";
import * as text from "./arduino/text";
import * as leaphy_common from "./arduino/variable_blocks";
import * as variables from "./arduino/variables";
import * as bluetooth from "./arduino/bluetooth";

arduino.default(generator);
leaphy_common.default(generator);
Expand All @@ -463,5 +464,6 @@ variables.default(generator);
lists.default(generator);
mesh.default(generator);
rtc.default(generator);
bluetooth.default(generator);

export default generator;
117 changes: 117 additions & 0 deletions packages/blocks/src/generators/arduino/bluetooth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Arduino } from "../arduino";
import { Block } from "blockly/core";

function getCodeGenerators(arduino: Arduino) {
arduino.forBlock["bluetooth_setup"] = function (block: Block) {
arduino.addInclude("leaphy_ble", "#include <LeaphyBLE.h>");
arduino.addInclude("arduino_ble", "#include <ArduinoBLE.h>");
arduino.addDeclaration("bluetooth", "LeaphyBLE LeaphyBLE;", true, 3);

const name = arduino.valueToCode(block, "NAME", arduino.ORDER_NONE);
let code = "";

if (block.workspace.getBlocksByType("bluetooth_on_connect").length > 0) {
code += "BLE.setEventHandler(BLEConnected, onBluetoothConnection);\n";
}

if (block.workspace.getBlocksByType("bluetooth_on_disconnect").length > 0) {
code += "BLE.setEventHandler(BLEDisconnected, onBluetoothDisconnection);\n";
}

if (block.workspace.getBlocksByType("bluetooth_on_discover").length > 0) {
code += "BLE.setEventHandler(BLEDiscovered, onDeviceDiscovered);\n";
}


block.workspace.getBlocksByType("bluetooth_create_binary_characteristic").forEach(add_binary_characteristic => {
const initialValue = arduino.valueToCode(add_binary_characteristic, "INITIAL_VALUE", arduino.ORDER_NONE) === "true";
const name = arduino.valueToCode(add_binary_characteristic, "NAME", arduino.ORDER_NONE);
code += `LeaphyBLE.addBinaryCharacteristic(${name}, ${initialValue});\n`;
});

block.workspace.getBlocksByType("bluetooth_create_string_characteristic").forEach(add_binary_characteristic => {
const initialValue = arduino.valueToCode(add_binary_characteristic, "INITIAL_VALUE", arduino.ORDER_NONE);
const name = arduino.valueToCode(add_binary_characteristic, "NAME", arduino.ORDER_NONE);
code += `LeaphyBLE.addStringCharacteristic(${name}, ${initialValue});\n`;
});

block.workspace.getBlocksByType("bluetooth_on_characteristic_update").forEach(ble_update_block => {
const name = arduino.valueToCode(ble_update_block, "NAME", arduino.ORDER_NONE);
code += `LeaphyBLE.getCharacteristicByName(${name})->setEventHandler(BLEWritten, [](BLEDevice central, BLECharacteristic characteristic) {\n`;
code += arduino.statementToCode(ble_update_block, "STACK");
code += "});\n";
});

code += `while (!LeaphyBLE.initialize(${name})) {}\n`;

// if (block.workspace.getBlocksByType("bluetooth_start_scan").length > 0) {
// code += `LeaphyBLE.scanForLeaphyDevices();\n`;
// }


arduino.addLoopTrap("bluetooth_setup", block);
return code;
};

arduino.forBlock["bluetooth_create_binary_characteristic"] = function (block: Block) {
return ``;
};

arduino.forBlock["bluetooth_create_string_characteristic"] = function (block: Block) {
return ``;
};

arduino.forBlock["bluetooth_on_connect"] = function (block: Block) {
const branch = arduino.statementToCode(block, "STACK");
const code =
`void onBluetoothConnection(BLEDevice device) {\n` + branch + "}\n";
arduino.addDeclaration("bluetooth_on_connect", code, true, 2);
return "BLE.poll();";
};

arduino.forBlock["bluetooth_on_disconnect"] = function (block: Block) {
const branch = arduino.statementToCode(block, "STACK");
const code =
`void onBluetoothDisconnection(BLEDevice device) {\n` + branch + "}\n";
arduino.addDeclaration("bluetooth_on_disconnect", code, true, 2);

return "BLE.poll();";
};

arduino.forBlock["bluetooth_on_characteristic_update"] = function (block: Block) {
return "BLE.poll();";
}

arduino.forBlock["bluetooth_on_discover"] = function (block: Block) {
const branch = arduino.statementToCode(block, "STACK");
const code =
`void onDeviceDiscovered(BLEDevice device) {\n` + branch + "}\n";
arduino.addDeclaration("bluetooth_on_discover", code, true, 2);
return "BLE.poll();";
};

arduino.forBlock["bluetooth_start_leaphy_filtered_scan"] = function (block: Block) {
return `LeaphyBLE.scanForLeaphyDevices();\n`;
}

arduino.forBlock["bluetooth_start_name_filtered_scan"] = function (block: Block) {
const name = arduino.valueToCode(block, "NAME", arduino.ORDER_NONE);
return`BLE.scanForName(${name});\n`;
}

arduino.forBlock["bluetooth_stop_scan"] = function (block: Block) {
return `LeaphyBLE.stopScanning();\n`;
}

arduino.forBlock["bluetooth_read_string_characteristic"] = function (block: Block) {
const name = arduino.valueToCode(block, "NAME", arduino.ORDER_NONE);
return [`(char *)LeaphyBLE.getCharacteristicByName(${name})->value()`, arduino.ORDER_ATOMIC];
};

arduino.forBlock["bluetooth_read_bool_characteristic"] = function (block: Block) {
const name = arduino.valueToCode(block, "NAME", arduino.ORDER_NONE);
return [`*LeaphyBLE.getCharacteristicByName(${name})->value() == 1`, arduino.ORDER_ATOMIC];
};
}

export default getCodeGenerators;
12 changes: 12 additions & 0 deletions packages/blocks/src/msg/translations/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,18 @@ messages.LEAPHY_MESH_CALL_PROCEDURE = "Roep mesh blok %1 aan op %2";
messages.LEAPHY_MESH_CALL_PROCEDURE_ALL = "Roep mesh blok %1 aan op alle %2";
messages.LEAPHY_MESH_ON_CONNECTION = "Wanneer verbinding wordt gemaakt";
messages.LEAPHY_MESH_CLIENT = "Afzender";
messages.LEAPHY_BLUETOOTH_SETUP = "Stel Bluetooth in met naam %1";
messages.LEAPHY_BLUETOOTH_ON_CONNECT = "Wanneer verbinding wordt gemaakt";
messages.LEAPHY_BLUETOOTH_ON_DISCONNECT = "Wanneer verbinding wordt verbroken";
messages.LEAPHY_BLUETOOTH_START_LEAPHY_FILTERED_SCAN = "Start scannen naar Leaphy's";
messages.LEAPHY_BLUETOOTH_START_NAME_FILTERED_SCAN = "Start scannen naar BLE apparaten met naam %1";
messages.LEAPHY_BLUETOOTH_STOP_SCAN = "Stop scannen";
messages.LEAPHY_BLUETOOTH_ON_DISCOVER = "Wanneer BLE-apparaat wordt ontdekt";
messages.LEAPHY_BLUETOOTH_CREATE_BINARY_CHARACTERISTIC = "Creeer binaire karakteristiek met identiteit\n%1 en beginwaarde %2";
messages.LEAPHY_BLUETOOTH_CREATE_STRING_CHARACTERISTIC = "Creeer string karakteristiek met identiteit\n%1 en beginwaarde %2";
messages.LEAPHY_BLUETOOTH_CHARACTERISTIC_ON_UPDATE = "Wanneer karakteristiek %1 wordt geupdate";
messages.LEAPHY_BLUETOOTH_READ_BINARY_CHARACTERISTIC = "Lees waarde van binaire karakteristiek %1";
messages.LEAPHY_BLUETOOTH_READ_STRING_CHARACTERISTIC = "Lees waarde van string karakteristiek %1";
messages.LEAPHY_RTC_GET = "Haal %1 op van tijd";
messages.LEAPHY_RTC_SET = "Stel tijd in op %1";
messages.LEAPHY_RTC_FORMAT = "Formatteer tijd";
Expand Down
2 changes: 2 additions & 0 deletions packages/blocks/src/theme/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const defaultBlockStyles = {
list_blocks: { colourPrimary: "#a500cf" },
procedure_blocks: { colourPrimary: "#4095CE" },
mesh_blocks: { colourPrimary: "#56cb9a" },
bluetooth_blocks: { colourPrimary: "#0082FC" },
};

const categoryStyles = {
Expand All @@ -18,6 +19,7 @@ const categoryStyles = {
lists_category: { colour: "#a500cf" },
functions_category: { colour: "#4095CE" },
mesh_category: { colour: "#56cb9a" },
bluetooth_category: { colour: "#0082FC" },
};

const componentStyles = {
Expand Down
Loading
Loading