From eca3bf16a1d2501100d1bf0a972430fe3f211ce9 Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 23 Jul 2020 16:04:00 +0200 Subject: [PATCH 01/12] add io blocks --- src/components/Blockly/BlocklyComponent.jsx | 7 +- src/components/Blockly/blocks/index.js | 4 +- src/components/Blockly/blocks/io.js | 257 +++++++++++++ .../Blockly/blocks/sensebox-telegram.js | 17 + src/components/Blockly/blocks/sensebox.js | 14 +- src/components/Blockly/generator/index.js | 2 + src/components/Blockly/generator/io.js | 32 ++ src/components/Blockly/generator/math.js | 344 ++++++++++++++++++ src/components/Blockly/helpers/board.js | 44 +++ src/components/Blockly/toolbox/Toolbox.js | 110 ++++++ src/components/Home.js | 27 +- 11 files changed, 817 insertions(+), 41 deletions(-) create mode 100644 src/components/Blockly/blocks/io.js create mode 100644 src/components/Blockly/blocks/sensebox-telegram.js create mode 100644 src/components/Blockly/generator/io.js create mode 100644 src/components/Blockly/generator/math.js create mode 100644 src/components/Blockly/helpers/board.js create mode 100644 src/components/Blockly/toolbox/Toolbox.js diff --git a/src/components/Blockly/BlocklyComponent.jsx b/src/components/Blockly/BlocklyComponent.jsx index 3bc97aa..631b25d 100644 --- a/src/components/Blockly/BlocklyComponent.jsx +++ b/src/components/Blockly/BlocklyComponent.jsx @@ -27,6 +27,7 @@ import './BlocklyComponent.css'; import Blockly from 'blockly/core'; //import locale from 'blockly/msg/en'; import 'blockly/blocks'; +import Toolbox from './toolbox/Toolbox'; //Blockly.setLocale(locale); @@ -61,13 +62,11 @@ class BlocklyComponent extends React.Component { } render() { - const { children } = this.props; + return
- - {children} - + ; } } diff --git a/src/components/Blockly/blocks/index.js b/src/components/Blockly/blocks/index.js index 3caa84b..e5c75e7 100644 --- a/src/components/Blockly/blocks/index.js +++ b/src/components/Blockly/blocks/index.js @@ -1,4 +1,6 @@ import './loops'; import './sensebox'; import './logic'; -import './sensebox-sensors'; \ No newline at end of file +import './sensebox-sensors'; +import './sensebox-telegram'; +import './io'; \ No newline at end of file diff --git a/src/components/Blockly/blocks/io.js b/src/components/Blockly/blocks/io.js new file mode 100644 index 0000000..f17149d --- /dev/null +++ b/src/components/Blockly/blocks/io.js @@ -0,0 +1,257 @@ +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Blocks for Arduino Digital and Analogue input and output + * functions. The Arduino function syntax can be found at + * http://arduino.cc/en/Reference/HomePage + * + * TODO: maybe change this to a "PIN" BlocklyType + */ +import { defineBlocksWithJsonArray } from 'blockly'; +import Blockly from 'blockly/core'; +import { selectedBoard } from '../helpers/board' + + +Blockly.Blocks['io_digitalwrite'] = { + /** + * Block for creating a 'set pin' to a state. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/DigitalWrite'); + this.setColour(250); + this.appendValueInput('STATE') + .appendField(Blockly.Msg.ARD_DIGITALWRITE) + .appendField(new Blockly.FieldDropdown( + selectedBoard().digitalPins), 'PIN') + .appendField(Blockly.Msg.ARD_WRITE_TO) + // .setCheck(Blockly.Types.BOOLEAN.checkList); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_DIGITALWRITE_TIP); + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown( + this, 'PIN', 'digitalPins'); + } +}; + +Blockly.Blocks['io_digitalread'] = { + /** + * Block for creating a 'read pin'. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/DigitalRead'); + this.setColour(250); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_DIGITALREAD) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.digitalPins), 'PIN'); + this.setOutput(true, Blockly.Types.BOOLEAN.output); + this.setTooltip(Blockly.Msg.ARD_DIGITALREAD_TIP); + }, + /** @return {!string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.BOOLEAN; + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown( + this, 'PIN', 'digitalPins'); + } +}; + +Blockly.Blocks['io_builtin_led'] = { + /** + * Block for setting built-in LED to a state. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/DigitalWrite'); + this.setColour(250); + this.appendValueInput('STATE') + .appendField(Blockly.Msg.ARD_BUILTIN_LED) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.builtinLed), 'BUILT_IN_LED') + .appendField(Blockly.Msg.ARD_WRITE_TO) + .setCheck(Blockly.Types.BOOLEAN.checkList); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_BUILTIN_LED_TIP); + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown( + this, 'BUILT_IN_LED', 'builtinLed'); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.BOOLEAN; + }, +}; + +Blockly.Blocks['io_analogwrite'] = { + /** + * Block for creating a 'set pin' to an analogue value. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/AnalogWrite'); + this.setColour(250); + this.appendValueInput('NUM') + .appendField(Blockly.Msg.ARD_ANALOGWRITE) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.pwmPins), 'PIN') + .appendField(Blockly.Msg.ARD_WRITE_TO) + .setCheck(Blockly.Types.NUMBER.output); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_ANALOGWRITE_TIP); + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown(this, 'PIN', 'pwmPins'); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + }, +}; + +Blockly.Blocks['io_analogread'] = { + /** + * Block for reading an analogue input. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/AnalogRead'); + this.setColour(250); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_ANALOGREAD) + .appendField(new Blockly.FieldDropdown( + Blockly.Arduino.Boards.selected.analogPins), 'PIN'); + this.setOutput(true, Blockly.Types.NUMBER.output); + this.setTooltip(Blockly.Msg.ARD_ANALOGREAD_TIP); + }, + /** @return {!string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + }, + /** + * Updates the content of the the pin related fields. + * @this Blockly.Block + */ + updateFields: function () { + Blockly.Arduino.Boards.refreshBlockFieldDropdown(this, 'PIN', 'analogPins'); + } +}; + +Blockly.Blocks['io_highlow'] = { + /** + * Block for creating a pin state. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/Constants'); + this.setColour(250); + this.appendDummyInput() + .appendField( + new Blockly.FieldDropdown([[Blockly.Msg.ARD_HIGH, 'HIGH'], [Blockly.Msg.ARD_LOW, 'LOW']]), + 'STATE'); + this.setOutput(true, Blockly.Types.BOOLEAN.output); + this.setTooltip(Blockly.Msg.ARD_HIGHLOW_TIP); + }, + /** @return {!string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.BOOLEAN; + } +}; + +Blockly.Blocks['io_pulsein'] = { + /** + * Block for measuring the duration of a pulse in an input pin. + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "type": "math_foo", + "message0": Blockly.Msg.ARD_PULSE_READ, + "args0": [{ + "type": "input_value", + "name": "PULSETYPE", + "check": Blockly.Types.BOOLEAN.check + }, { + "type": "field_dropdown", + "name": "PULSEPIN", + "options": Blockly.Arduino.Boards.selected.digitalPins + } + ], + "output": Blockly.Types.NUMBER.output, + "inputsInline": true, + "colour": 250, + "tooltip": Blockly.Msg.ARD_PULSE_TIP, + "helpUrl": 'https://www.arduino.cc/en/Reference/PulseIn' + }); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + } +}; + +Blockly.Blocks['io_pulsetimeout'] = { + /** + * Block for measuring (with a time-out) the duration of a pulse in an input + * pin. + * @this Blockly.Block + */ + init: function () { + this.jsonInit({ + "type": "math_foo", + "message0": Blockly.Msg.ARD_PULSE_READ_TIMEOUT, + "args0": [{ + "type": "input_value", + "name": "PULSETYPE", + "check": Blockly.Types.BOOLEAN.check + }, { + "type": "field_dropdown", + "name": "PULSEPIN", + "options": Blockly.Arduino.Boards.selected.digitalPins + }, { + "type": "input_value", + "name": "TIMEOUT", + "check": Blockly.Types.NUMBER.check + } + ], + "output": Blockly.Types.NUMBER.output, + "inputsInline": true, + "colour": 250, + "tooltip": Blockly.Msg.ARD_PULSETIMEOUT_TIP, + "helpUrl": 'https://www.arduino.cc/en/Reference/PulseIn' + }); + }, + /** @return {!string} The type of input value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.NUMBER; + } +}; diff --git a/src/components/Blockly/blocks/sensebox-telegram.js b/src/components/Blockly/blocks/sensebox-telegram.js new file mode 100644 index 0000000..2ba704d --- /dev/null +++ b/src/components/Blockly/blocks/sensebox-telegram.js @@ -0,0 +1,17 @@ +import Blockly from 'blockly'; + +Blockly.Blocks["sensebox_telegram"] = { + init: function () { + this.setColour(120); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_telegram_init); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField("telegram") + .appendField(new Blockly.FieldTextInput("token"), "telegram_token"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + + diff --git a/src/components/Blockly/blocks/sensebox.js b/src/components/Blockly/blocks/sensebox.js index 18ce462..43ebcbb 100644 --- a/src/components/Blockly/blocks/sensebox.js +++ b/src/components/Blockly/blocks/sensebox.js @@ -1,16 +1,4 @@ import Blockly from 'blockly'; -Blockly.Blocks["sensebox_telegram"] = { - init: function () { - this.setColour(120); - this.appendDummyInput() - .appendField(Blockly.Msg.senseBox_telegram_init); - this.appendDummyInput() - .setAlign(Blockly.ALIGN_LEFT) - .appendField("telegram") - .appendField(new Blockly.FieldTextInput("token"), "telegram_token"); - this.setPreviousStatement(true, null); - this.setNextStatement(true, null); - } -}; + diff --git a/src/components/Blockly/generator/index.js b/src/components/Blockly/generator/index.js index 271af4a..c629df3 100644 --- a/src/components/Blockly/generator/index.js +++ b/src/components/Blockly/generator/index.js @@ -2,4 +2,6 @@ import './generator'; import './loops'; import './sensebox'; import './logic'; +import './math'; +import './io'; diff --git a/src/components/Blockly/generator/io.js b/src/components/Blockly/generator/io.js new file mode 100644 index 0000000..5cef62a --- /dev/null +++ b/src/components/Blockly/generator/io.js @@ -0,0 +1,32 @@ +import * as Blockly from 'blockly/core'; +import { Block } from 'blockly'; + +/** + * Function for 'set pin' (X) to a state (Y). + * Arduino code: setup { pinMode(X, OUTPUT); } + * loop { digitalWrite(X, Y); } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['io_digitalwrite'] = function (block) { + var pin = block.getFieldValue('PIN'); + var stateOutput = Blockly.Arduino.valueToCode( + block, 'STATE', Blockly['Arduino'].ORDER_ATOMIC) || 'LOW'; + Blockly['Arduino'].setupCode_['pinMode'] = 'pinMode(' + pin + ', OUTPUT);'; + var code = 'digitalWrite(' + pin + ', ' + stateOutput + ');\n'; + return code; +}; + +/** + * Function for reading a digital pin (X). + * Arduino code: setup { pinMode(X, INPUT); } + * loop { digitalRead(X) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['io_digitalread'] = function (block) { + var pin = block.getFieldValue('PIN'); + Blockly['Arduino'].setupCode_['pinMode' + pin] = 'pinMode(' + pin + ', INPUT);' + var code = 'digitalRead(' + pin + ')'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; diff --git a/src/components/Blockly/generator/math.js b/src/components/Blockly/generator/math.js new file mode 100644 index 0000000..0832e0c --- /dev/null +++ b/src/components/Blockly/generator/math.js @@ -0,0 +1,344 @@ + +import * as Blockly from 'blockly/core'; +import { Block } from 'blockly'; + +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Generating Arduino code for the Math blocks. + * + * TODO: Math on list needs lists to be implemented. + * math_constant and math_change needs to be tested in compiler. + */ + +/** + * Generator for a numeric value (X). + * Arduino code: loop { X } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_number'] = function (block) { + // Numeric value. + var code = parseFloat(block.getFieldValue('NUM')); + if (code == Infinity) { + code = 'INFINITY'; + } else if (code == -Infinity) { + code = '-INFINITY'; + } + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * Generator for a basic arithmetic operators (X and Y) and power function + * (X ^ Y). + * Arduino code: loop { X operator Y } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_arithmetic'] = function (block) { + var OPERATORS = { + ADD: [' + ', Blockly.Arduino.ORDER_ADDITIVE], + MINUS: [' - ', Blockly.Arduino.ORDER_ADDITIVE], + MULTIPLY: [' * ', Blockly.Arduino.ORDER_MULTIPLICATIVE], + DIVIDE: [' / ', Blockly.Arduino.ORDER_MULTIPLICATIVE], + POWER: [null, Blockly.Arduino.ORDER_NONE] // Handle power separately. + }; + var tuple = OPERATORS[block.getFieldValue('OP')]; + var operator = tuple[0]; + var order = tuple[1]; + var argument0 = Blockly.Arduino.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'B', order) || '0'; + var code; + // Power in C++ requires a special case since it has no operator. + if (!operator) { + code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; + } + code = argument0 + operator + argument1; + return [code, order]; +}; + +/** + * Generator for math operators that contain a single operand (X). + * Arduino code: loop { operator(X) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_single'] = function (block) { + var operator = block.getFieldValue('OP'); + var code; + var arg; + if (operator == 'NEG') { + // Negation is a special case given its different operator precedents. + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_UNARY_PREFIX) || '0'; + if (arg[0] == '-') { + // --3 is not legal in C++ in this context. + arg = ' ' + arg; + } + code = '-' + arg; + return [code, Blockly.Arduino.ORDER_UNARY_PREFIX]; + } + if (operator == 'ABS' || operator.substring(0, 5) == 'ROUND') { + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_UNARY_POSTFIX) || '0'; + } else if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + } else { + arg = Blockly.Arduino.valueToCode(block, 'NUM', + Blockly.Arduino.ORDER_NONE) || '0'; + } + // First, handle cases which generate values that don't need parentheses. + switch (operator) { + case 'ABS': + code = 'abs(' + arg + ')'; + break; + case 'ROOT': + code = 'sqrt(' + arg + ')'; + break; + case 'LN': + code = 'log(' + arg + ')'; + break; + case 'EXP': + code = 'exp(' + arg + ')'; + break; + case 'POW10': + code = 'pow(10,' + arg + ')'; + break; + case 'ROUND': + code = 'round(' + arg + ')'; + break; + case 'ROUNDUP': + code = 'ceil(' + arg + ')'; + break; + case 'ROUNDDOWN': + code = 'floor(' + arg + ')'; + break; + case 'SIN': + code = 'sin(' + arg + ' / 180 * Math.PI)'; + break; + case 'COS': + code = 'cos(' + arg + ' / 180 * Math.PI)'; + break; + case 'TAN': + code = 'tan(' + arg + ' / 180 * Math.PI)'; + break; + } + if (code) { + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; + } + // Second, handle cases which generate values that may need parentheses. + switch (operator) { + case 'LOG10': + code = 'log(' + arg + ') / log(10)'; + break; + case 'ASIN': + code = 'asin(' + arg + ') / M_PI * 180'; + break; + case 'ACOS': + code = 'acos(' + arg + ') / M_PI * 180'; + break; + case 'ATAN': + code = 'atan(' + arg + ') / M_PI * 180'; + break; + default: + throw 'Unknown math operator: ' + operator; + } + return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE]; +}; + +/** + * Generator for math constants (PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), + * INFINITY). + * Arduino code: loop { constant } + * TODO: Might need to include "#define _USE_MATH_DEFINES" + * The arduino header file already includes math.h + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['math_constant'] = function (block) { + var CONSTANTS = { + 'PI': ['M_PI', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'E': ['M_E', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'GOLDEN_RATIO': ['(1 + sqrt(5)) / 2', Blockly.Arduino.ORDER_MULTIPLICATIVE], + 'SQRT2': ['M_SQRT2', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'SQRT1_2': ['M_SQRT1_2', Blockly.Arduino.ORDER_UNARY_POSTFIX], + 'INFINITY': ['INFINITY', Blockly.Arduino.ORDER_ATOMIC] + }; + return CONSTANTS[block.getFieldValue('CONSTANT')]; +}; + +/** + * Generator for math checks: if a number is even, odd, prime, whole, positive, + * negative, or if it is divisible by certain number. Returns true or false. + * Arduino code: complex code, can create external functions. + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_number_property'] = function (block) { + var number_to_check = Blockly.Arduino.valueToCode(block, 'NUMBER_TO_CHECK', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + var dropdown_property = block.getFieldValue('PROPERTY'); + var code; + if (dropdown_property == 'PRIME') { + var func = [ + 'boolean ' + Blockly.Arduino.DEF_FUNC_NAME + '(int n) {', + ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods', + ' if (n == 2 || n == 3) {', + ' return true;', + ' }', + ' // False if n is NaN, negative, is 1.', + ' // And false if n is divisible by 2 or 3.', + ' if (isnan(n) || (n <= 1) || (n == 1) || (n % 2 == 0) || ' + + '(n % 3 == 0)) {', + ' return false;', + ' }', + ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).', + ' for (int x = 6; x <= sqrt(n) + 1; x += 6) {', + ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {', + ' return false;', + ' }', + ' }', + ' return true;', + '}']; + var funcName = Blockly.Arduino.addFunction('mathIsPrime', func.join('\n')); + Blockly.Arduino.addInclude('math', '#include '); + code = funcName + '(' + number_to_check + ')'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; + } + switch (dropdown_property) { + case 'EVEN': + code = number_to_check + ' % 2 == 0'; + break; + case 'ODD': + code = number_to_check + ' % 2 == 1'; + break; + case 'WHOLE': + Blockly.Arduino.addInclude('math', '#include '); + code = '(floor(' + number_to_check + ') == ' + number_to_check + ')'; + break; + case 'POSITIVE': + code = number_to_check + ' > 0'; + break; + case 'NEGATIVE': + code = number_to_check + ' < 0'; + break; + case 'DIVISIBLE_BY': + var divisor = Blockly.Arduino.valueToCode(block, 'DIVISOR', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + code = number_to_check + ' % ' + divisor + ' == 0'; + break; + } + return [code, Blockly.Arduino.ORDER_EQUALITY]; +}; + +/** + * Generator to add (Y) to a variable (X). + * If variable X has not been declared before this block it will be declared as + * a (not initialised) global int, however globals are 0 initialised in C/C++. + * Arduino code: loop { X += Y; } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_change'] = function (block) { + var argument0 = Blockly.Arduino.valueToCode(block, 'DELTA', + Blockly.Arduino.ORDER_ADDITIVE) || '0'; + var varName = Blockly.Arduino.variableDB_.getName( + block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + return varName + ' += ' + argument0 + ';\n'; +}; + +/** Rounding functions have a single operand. */ +Blockly.Arduino['math_round'] = Blockly.Arduino['math_single']; + +/** Trigonometry functions have a single operand. */ +Blockly.Arduino['math_trig'] = Blockly.Arduino['math_single']; + +/** + * Generator for the math function to a list. + * Arduino code: ??? + * TODO: List have to be implemented first. Removed from toolbox for now. + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_on_list'] = Blockly.Arduino.noGeneratorCodeInline; + +/** + * Generator for the math modulo function (calculates remainder of X/Y). + * Arduino code: loop { X % Y } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_modulo'] = function (block) { + var argument0 = Blockly.Arduino.valueToCode(block, 'DIVIDEND', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'DIVISOR', + Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; + var code = argument0 + ' % ' + argument1; + return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE]; +}; + +/** + * Generator for clipping a number(X) between two limits (Y and Z). + * Arduino code: loop { (X < Y ? Y : ( X > Z ? Z : X)) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_constrain'] = function (block) { + // Constrain a number between two limits. + var argument0 = Blockly.Arduino.valueToCode(block, 'VALUE', + Blockly.Arduino.ORDER_NONE) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'LOW', + Blockly.Arduino.ORDER_NONE) || '0'; + var argument2 = Blockly.Arduino.valueToCode(block, 'HIGH', + Blockly.Arduino.ORDER_NONE) || '0'; + var code = '(' + argument0 + ' < ' + argument1 + ' ? ' + argument1 + + ' : ( ' + argument0 + ' > ' + argument2 + ' ? ' + argument2 + ' : ' + + argument0 + '))'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; +}; + +/** + * Generator for a random integer between two numbers (X and Y). + * Arduino code: loop { math_random_int(X, Y); } + * and an aditional math_random_int function + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['math_random_int'] = function (block) { + var argument0 = Blockly.Arduino.valueToCode(block, 'FROM', + Blockly.Arduino.ORDER_NONE) || '0'; + var argument1 = Blockly.Arduino.valueToCode(block, 'TO', + Blockly.Arduino.ORDER_NONE) || '0'; + var functionName = Blockly.Arduino.variableDB_.getDistinctName( + 'math_random_int', Blockly.Generator.NAME_TYPE); + Blockly.Arduino.setups_['init_rand'] = 'randomSeed(analogRead(0));'; + Blockly.Arduino.math_random_int.random_function = functionName; + var func = [ + 'int ' + Blockly.Arduino.DEF_FUNC_NAME + '(int min, int max) {', + ' if (min > max) {', + ' // Swap min and max to ensure min is smaller.', + ' int temp = min;', + ' min = max;', + ' max = temp;', + ' }', + ' return min + (rand() % (max - min + 1));', + '}']; + var funcName = Blockly.Arduino.addFunction('mathRandomInt', func.join('\n')); + var code = funcName + '(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; +}; + +/** + * Generator for a random float from 0 to 1. + * Arduino code: loop { (rand() / RAND_MAX) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['math_random_float'] = function (block) { + return ['(rand() / RAND_MAX)', Blockly.Arduino.ORDER_UNARY_POSTFIX]; +}; diff --git a/src/components/Blockly/helpers/board.js b/src/components/Blockly/helpers/board.js new file mode 100644 index 0000000..f6fc279 --- /dev/null +++ b/src/components/Blockly/helpers/board.js @@ -0,0 +1,44 @@ +/** + * Define boards and pins + * + */ +const sensebox_mcu = { + description: 'senseBox Microcontroller Unit based on Microchip SAMD21G18A', + compilerFlag: 'arduino:samd', + digitalPins: [['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + digitalPinsLED: [['BUILTIN_1', '7'], ['BUILTIN_2', '8'], ['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + digitalPinsButton: [['on Board', '0'], ['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + pwmPins: [['D1', '1'], ['D2', '2'], ['D3', '3'], ['D4', '4'], ['D5', '5'], ['D6', '6']], + serial: [['serial', 'SerialUSB'], ['serial_1', 'Serial1'], ['serial_2', 'Serial2']], + serialPins: { + SerialUSB: [['RX', ''], ['TX', '']], + Serial1: [['RX', '11'], ['TX', '10']], + Serial2: [['RX', '13'], ['TX', '12']] + }, + serialSpeed: [['300', '300'], ['600', '600'], ['1200', '1200'], + ['2400', '2400'], ['4800', '4800'], ['9600', '9600'], + ['14400', '14400'], ['19200', '19200'], ['28800', '28800'], + ['31250', '31250'], ['38400', '38400'], ['57600', '57600'], + ['115200', '115200']], + spi: [['SPI', 'SPI']], + spiPins: { SPI: [['MOSI', '19'], ['MISO', '21'], ['SCK', '20']] }, + spiClockDivide: [['2 (8MHz)', 'SPI_CLOCK_DIV2'], + ['4 (4MHz)', 'SPI_CLOCK_DIV4'], + ['8 (2MHz)', 'SPI_CLOCK_DIV8'], + ['16 (1MHz)', 'SPI_CLOCK_DIV16'], + ['32 (500KHz)', 'SPI_CLOCK_DIV32'], + ['64 (250KHz)', 'SPI_CLOCK_DIV64'], + ['128 (125KHz)', 'SPI_CLOCK_DIV128']], + i2c: [['I2C', 'Wire']], + i2cPins: { Wire: [['SDA', '17'], ['SCL', '16']] }, + i2cSpeed: [['100kHz', '100000L'], ['400kHz', '400000L']], + builtinLed: [['BUILTIN_1', '7'], ['BUILTIN_2', '8']], + interrupt: [['interrupt1', '1'], ['interrupt2', '2'], , ['interrupt3', '3'], ['interrupt4', '4'], ['interrupt5', '5'], ['interrupt6', '6']], + analogPins: [['A1', 'A1'], ['A2', 'A2'], ['A3', 'A3'], ['A4', 'A4'], ['A5', 'A5'], ['A6', 'A6']], + serial_baud_rate: 9600, + parseKey: '_*_' +}; + +export const selectedBoard = () => { + return sensebox_mcu; +}; diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js new file mode 100644 index 0000000..ccbf34d --- /dev/null +++ b/src/components/Blockly/toolbox/Toolbox.js @@ -0,0 +1,110 @@ +import React, { Component } from 'react'; +import BlocklyComponent, { Block, Value, Field, Shadow, Category } from '../'; + + +class Toolbox extends React.Component { + constructor(props) { + super(props); + } + + render() { + return ( + + + + + + + + + + + + + + + + + + + + + + 10 + + + + + + + + 1 + + + + + 10 + + + + + 1 + + + + + + + + + + + + + + + + 1 + + + + + + + + + 1 + + + + + 100 + + + + + + + 1 + + + + + 100 + + + + + {/* */} + + + + + + + + ); + }; +} + +export default Toolbox; \ No newline at end of file diff --git a/src/components/Home.js b/src/components/Home.js index 289b155..64b4237 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -7,8 +7,9 @@ import BlocklyComponent, { Block, Value, Field, Shadow, Category } from './Block import * as Blockly from 'blockly/core'; import * as De from './Blockly/msg/de'; // de locale files //import * as En from './Blockly/msg/en'; // de locale files -import './Blockly/blocks/index'; -import './Blockly/generator/index'; +import './Blockly/blocks/'; +import './Blockly/generator/'; + @@ -43,27 +44,7 @@ class Home extends React.Component { drag: true, wheel: true }} - initialXml={''}> - - - - - - - - - - - - - - - - - - - - + initialXml={''} />
); From 440622a66c557e3658c740c82681275b59919a0c Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 11:10:22 +0200 Subject: [PATCH 02/12] add sensebox sensor blocks --- src/actions/workspaceActions.js | 74 ++--- src/components/Blockly/BlocklyComponent.css | 3 +- src/components/Blockly/BlocklyComponent.jsx | 5 +- src/components/Blockly/BlocklyWindow.js | 36 +-- src/components/Blockly/blocks/index.js | 8 +- src/components/Blockly/blocks/io.js | 49 +-- src/components/Blockly/blocks/logic.js | 251 ++++++++++++--- src/components/Blockly/blocks/math.js | 2 + src/components/Blockly/blocks/procedures.js | 38 +++ .../Blockly/blocks/sensebox-display.js | 0 .../Blockly/blocks/sensebox-osem.js | 114 +++++++ .../Blockly/blocks/sensebox-sensors.js | 298 +++++++++++++++++- .../Blockly/blocks/sensebox-telegram.js | 38 ++- src/components/Blockly/blocks/time.js | 130 ++++++++ src/components/Blockly/generator/generator.js | 59 +++- src/components/Blockly/generator/index.js | 7 +- src/components/Blockly/generator/io.js | 83 +++++ src/components/Blockly/generator/logic.js | 2 +- .../Blockly/generator/procedures.js | 30 ++ .../Blockly/generator/sensebox-osem.js | 178 +++++++++++ .../Blockly/generator/sensebox-sensors.js | 227 ++++++++++++- .../Blockly/generator/sensebox-telegram.js | 58 ++++ src/components/Blockly/generator/sensebox.js | 16 - src/components/Blockly/generator/time.js | 80 +++++ src/components/Blockly/helpers/colour.js | 16 + src/components/Blockly/helpers/types.js | 221 +++++++++++++ src/components/Blockly/toolbox/Toolbox.js | 72 ++++- src/components/Home.js | 1 + 28 files changed, 1919 insertions(+), 177 deletions(-) create mode 100644 src/components/Blockly/blocks/math.js create mode 100644 src/components/Blockly/blocks/procedures.js create mode 100644 src/components/Blockly/blocks/sensebox-display.js create mode 100644 src/components/Blockly/blocks/sensebox-osem.js create mode 100644 src/components/Blockly/blocks/time.js create mode 100644 src/components/Blockly/generator/procedures.js create mode 100644 src/components/Blockly/generator/sensebox-osem.js create mode 100644 src/components/Blockly/generator/sensebox-telegram.js create mode 100644 src/components/Blockly/generator/time.js create mode 100644 src/components/Blockly/helpers/colour.js create mode 100644 src/components/Blockly/helpers/types.js diff --git a/src/actions/workspaceActions.js b/src/actions/workspaceActions.js index 006d15f..40d837d 100644 --- a/src/actions/workspaceActions.js +++ b/src/actions/workspaceActions.js @@ -10,49 +10,49 @@ export const workspaceChange = () => (dispatch) => { export const onChangeWorkspace = (event) => (dispatch, getState) => { + dispatch({ + type: CHANGE_WORKSPACE, + }) + const workspace = Blockly.getMainWorkspace(); + var code = getState().workspace.code; + code.arduino = Blockly.Arduino.workspaceToCode(workspace); + var xmlDom = Blockly.Xml.workspaceToDom(workspace); + code.xml = Blockly.Xml.domToPrettyText(xmlDom); + dispatch({ + type: NEW_CODE, + payload: code + }); + var stats = getState().workspace.stats; + if (event.type === Blockly.Events.BLOCK_CREATE) { + stats.create += event.ids.length; dispatch({ - type: CHANGE_WORKSPACE, - }) - const workspace = Blockly.getMainWorkspace(); - var code = getState().workspace.code; - code.arduino = Blockly.Arduino.workspaceToCode(workspace); - var xmlDom = Blockly.Xml.workspaceToDom(workspace); - code.xml = Blockly.Xml.domToPrettyText(xmlDom); - dispatch({ - type: NEW_CODE, - payload: code + type: CREATE_BLOCK, + payload: stats }); - var stats = getState().workspace.stats; - if (event.type === Blockly.Events.BLOCK_CREATE){ - stats.create += event.ids.length; + } + else if (event.type === Blockly.Events.BLOCK_MOVE) { + stats.move += 1; + dispatch({ + type: MOVE_BLOCK, + payload: stats + }); + } + else if (event.type === Blockly.Events.BLOCK_CHANGE) { + stats.change += 1; + dispatch({ + type: CHANGE_BLOCK, + payload: stats + }); + } + else if (event.type === Blockly.Events.BLOCK_DELETE) { + if (stats.create > 0) { + stats.delete += event.ids.length; dispatch({ - type: CREATE_BLOCK, + type: DELETE_BLOCK, payload: stats }); } - else if (event.type === Blockly.Events.BLOCK_MOVE){ - stats.move += 1; - dispatch({ - type: MOVE_BLOCK, - payload: stats - }); - } - else if (event.type === Blockly.Events.BLOCK_CHANGE){ - stats.change += 1; - dispatch({ - type: CHANGE_BLOCK, - payload: stats - }); - } - else if (event.type === Blockly.Events.BLOCK_DELETE){ - if(stats.create > 0){ - stats.delete += event.ids.length; - dispatch({ - type: DELETE_BLOCK, - payload: stats - }); - } - } + } }; export const clearStats = () => (dispatch) => { diff --git a/src/components/Blockly/BlocklyComponent.css b/src/components/Blockly/BlocklyComponent.css index 14db59a..ce2c211 100644 --- a/src/components/Blockly/BlocklyComponent.css +++ b/src/components/Blockly/BlocklyComponent.css @@ -1,6 +1,7 @@ #blocklyDiv { height: 100%; - min-height: 500px; + min-height: 700px; width: 100%; border: 1px solid #4EAF47; + position: relative; } diff --git a/src/components/Blockly/BlocklyComponent.jsx b/src/components/Blockly/BlocklyComponent.jsx index 631b25d..50d8578 100644 --- a/src/components/Blockly/BlocklyComponent.jsx +++ b/src/components/Blockly/BlocklyComponent.jsx @@ -25,11 +25,12 @@ import React from 'react'; import './BlocklyComponent.css'; import Blockly from 'blockly/core'; -//import locale from 'blockly/msg/en'; +import locale from 'blockly/msg/en'; import 'blockly/blocks'; import Toolbox from './toolbox/Toolbox'; -//Blockly.setLocale(locale); + +Blockly.setLocale(locale); class BlocklyComponent extends React.Component { constructor(props) { diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js index 8ad7486..f507bad 100644 --- a/src/components/Blockly/BlocklyWindow.js +++ b/src/components/Blockly/BlocklyWindow.js @@ -5,12 +5,13 @@ import { onChangeWorkspace } from '../../actions/workspaceActions'; import BlocklyComponent, { Block, Value, Field, Shadow, Category } from './'; import * as Blockly from 'blockly/core'; -import * as De from './msg/de'; // de locale files -//import * as En from './Blockly/msg/en'; // de locale files +//import * as De from './msg/de'; // de locale files +import * as En from './msg/en'; // en locale files import './blocks/index'; import './generator/index'; + class BlocklyWindow extends Component { constructor(props) { @@ -23,6 +24,7 @@ class BlocklyWindow extends Component { this.props.onChangeWorkspace({}); workspace.addChangeListener((event) => { this.props.onChangeWorkspace(event); + Blockly.Events.disableOrphans(event); }); } @@ -31,10 +33,11 @@ class BlocklyWindow extends Component { + `} > - - - - - - - - - - - - - - - - - - - - + + ); }; } diff --git a/src/components/Blockly/blocks/index.js b/src/components/Blockly/blocks/index.js index e5c75e7..c466260 100644 --- a/src/components/Blockly/blocks/index.js +++ b/src/components/Blockly/blocks/index.js @@ -3,4 +3,10 @@ import './sensebox'; import './logic'; import './sensebox-sensors'; import './sensebox-telegram'; -import './io'; \ No newline at end of file +import './sensebox-osem'; +import './io'; +import './math'; +import './procedures'; +import './time'; + +import '../helpers/types' \ No newline at end of file diff --git a/src/components/Blockly/blocks/io.js b/src/components/Blockly/blocks/io.js index f17149d..104b3f4 100644 --- a/src/components/Blockly/blocks/io.js +++ b/src/components/Blockly/blocks/io.js @@ -13,6 +13,7 @@ import { defineBlocksWithJsonArray } from 'blockly'; import Blockly from 'blockly/core'; import { selectedBoard } from '../helpers/board' +import * as Types from '../helpers/types' Blockly.Blocks['io_digitalwrite'] = { @@ -28,7 +29,7 @@ Blockly.Blocks['io_digitalwrite'] = { .appendField(new Blockly.FieldDropdown( selectedBoard().digitalPins), 'PIN') .appendField(Blockly.Msg.ARD_WRITE_TO) - // .setCheck(Blockly.Types.BOOLEAN.checkList); + .setCheck(Types.BOOLEAN.checkList); this.setInputsInline(false); this.setPreviousStatement(true, null); this.setNextStatement(true, null); @@ -55,13 +56,13 @@ Blockly.Blocks['io_digitalread'] = { this.appendDummyInput() .appendField(Blockly.Msg.ARD_DIGITALREAD) .appendField(new Blockly.FieldDropdown( - Blockly.Arduino.Boards.selected.digitalPins), 'PIN'); - this.setOutput(true, Blockly.Types.BOOLEAN.output); + selectedBoard().digitalPins), 'PIN'); + this.setOutput(true, Types.BOOLEAN); this.setTooltip(Blockly.Msg.ARD_DIGITALREAD_TIP); }, /** @return {!string} The type of return value for the block, an integer. */ getBlockType: function () { - return Blockly.Types.BOOLEAN; + return Types.BOOLEAN; }, /** * Updates the content of the the pin related fields. @@ -84,9 +85,9 @@ Blockly.Blocks['io_builtin_led'] = { this.appendValueInput('STATE') .appendField(Blockly.Msg.ARD_BUILTIN_LED) .appendField(new Blockly.FieldDropdown( - Blockly.Arduino.Boards.selected.builtinLed), 'BUILT_IN_LED') + selectedBoard().builtinLed), 'BUILT_IN_LED') .appendField(Blockly.Msg.ARD_WRITE_TO) - .setCheck(Blockly.Types.BOOLEAN.checkList); + .setCheck(Types.BOOLEAN.compatibleTypes); this.setInputsInline(false); this.setPreviousStatement(true, null); this.setNextStatement(true, null); @@ -102,7 +103,7 @@ Blockly.Blocks['io_builtin_led'] = { }, /** @return {!string} The type of input value for the block, an integer. */ getBlockType: function () { - return Blockly.Types.BOOLEAN; + return Types.BOOLEAN; }, }; @@ -117,9 +118,9 @@ Blockly.Blocks['io_analogwrite'] = { this.appendValueInput('NUM') .appendField(Blockly.Msg.ARD_ANALOGWRITE) .appendField(new Blockly.FieldDropdown( - Blockly.Arduino.Boards.selected.pwmPins), 'PIN') + selectedBoard().pwmPins), 'PIN') .appendField(Blockly.Msg.ARD_WRITE_TO) - .setCheck(Blockly.Types.NUMBER.output); + .setCheck(Types.NUMBER.compatibleTypes); this.setInputsInline(false); this.setPreviousStatement(true, null); this.setNextStatement(true, null); @@ -134,7 +135,7 @@ Blockly.Blocks['io_analogwrite'] = { }, /** @return {!string} The type of input value for the block, an integer. */ getBlockType: function () { - return Blockly.Types.NUMBER; + return Types.NUMBER; }, }; @@ -149,13 +150,13 @@ Blockly.Blocks['io_analogread'] = { this.appendDummyInput() .appendField(Blockly.Msg.ARD_ANALOGREAD) .appendField(new Blockly.FieldDropdown( - Blockly.Arduino.Boards.selected.analogPins), 'PIN'); - this.setOutput(true, Blockly.Types.NUMBER.output); + selectedBoard().analogPins), 'PIN'); + this.setOutput(true, Types.NUMBER.typeId); this.setTooltip(Blockly.Msg.ARD_ANALOGREAD_TIP); }, /** @return {!string} The type of return value for the block, an integer. */ getBlockType: function () { - return Blockly.Types.NUMBER; + return Types.NUMBER.typeId; }, /** * Updates the content of the the pin related fields. @@ -178,12 +179,12 @@ Blockly.Blocks['io_highlow'] = { .appendField( new Blockly.FieldDropdown([[Blockly.Msg.ARD_HIGH, 'HIGH'], [Blockly.Msg.ARD_LOW, 'LOW']]), 'STATE'); - this.setOutput(true, Blockly.Types.BOOLEAN.output); + this.setOutput(true, Types.BOOLEAN.typeId); this.setTooltip(Blockly.Msg.ARD_HIGHLOW_TIP); }, /** @return {!string} The type of return value for the block, an integer. */ getBlockType: function () { - return Blockly.Types.BOOLEAN; + return Types.BOOLEAN; } }; @@ -199,14 +200,14 @@ Blockly.Blocks['io_pulsein'] = { "args0": [{ "type": "input_value", "name": "PULSETYPE", - "check": Blockly.Types.BOOLEAN.check + "check": Types.BOOLEAN.compatibleTypes }, { "type": "field_dropdown", "name": "PULSEPIN", - "options": Blockly.Arduino.Boards.selected.digitalPins + "options": selectedBoard().digitalPins, } ], - "output": Blockly.Types.NUMBER.output, + "output": Types.NUMBER.typeId, "inputsInline": true, "colour": 250, "tooltip": Blockly.Msg.ARD_PULSE_TIP, @@ -215,7 +216,7 @@ Blockly.Blocks['io_pulsein'] = { }, /** @return {!string} The type of input value for the block, an integer. */ getBlockType: function () { - return Blockly.Types.NUMBER; + return Types.NUMBER.typeId; } }; @@ -232,18 +233,18 @@ Blockly.Blocks['io_pulsetimeout'] = { "args0": [{ "type": "input_value", "name": "PULSETYPE", - "check": Blockly.Types.BOOLEAN.check + "check": Types.BOOLEAN.compatibleTypes }, { "type": "field_dropdown", "name": "PULSEPIN", - "options": Blockly.Arduino.Boards.selected.digitalPins + "options": selectedBoard().digitalPins, }, { "type": "input_value", "name": "TIMEOUT", - "check": Blockly.Types.NUMBER.check + "check": Types.NUMBER.compatibleTypes } ], - "output": Blockly.Types.NUMBER.output, + "output": Types.NUMBER.typeId, "inputsInline": true, "colour": 250, "tooltip": Blockly.Msg.ARD_PULSETIMEOUT_TIP, @@ -252,6 +253,6 @@ Blockly.Blocks['io_pulsetimeout'] = { }, /** @return {!string} The type of input value for the block, an integer. */ getBlockType: function () { - return Blockly.Types.NUMBER; + return Types.NUMBER.typeId; } }; diff --git a/src/components/Blockly/blocks/logic.js b/src/components/Blockly/blocks/logic.js index 98a1734..0ba9179 100644 --- a/src/components/Blockly/blocks/logic.js +++ b/src/components/Blockly/blocks/logic.js @@ -1,61 +1,236 @@ import { defineBlocksWithJsonArray } from 'blockly'; import Blockly from 'blockly/core'; -defineBlocksWithJsonArray([ + + + +Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT + // Block for boolean data type: true and false. + { + "type": "logic_boolean", + "message0": "%1", + "args0": [ + { + "type": "field_dropdown", + "name": "BOOL", + "options": [ + ["%{BKY_LOGIC_BOOLEAN_TRUE}", "TRUE"], + ["%{BKY_LOGIC_BOOLEAN_FALSE}", "FALSE"] + ] + } + ], + "output": "Boolean", + "style": "logic_blocks", + "tooltip": "%{BKY_LOGIC_BOOLEAN_TOOLTIP}", + "helpUrl": "%{BKY_LOGIC_BOOLEAN_HELPURL}" + }, + // Block for if/elseif/else condition. + { + "type": "controls_if", + "message0": "%{BKY_CONTROLS_IF_MSG_IF} %1", + "args0": [ + { + "type": "input_value", + "name": "IF0", + "check": "Boolean" + } + ], + "message1": "%{BKY_CONTROLS_IF_MSG_THEN} %1", + "args1": [ + { + "type": "input_statement", + "name": "DO0" + } + ], + "previousStatement": null, + "nextStatement": null, + "style": "logic_blocks", + "helpUrl": "%{BKY_CONTROLS_IF_HELPURL}", + "mutator": "controls_if_mutator", + "extensions": ["controls_if_tooltip"] + }, // If/else block that does not use a mutator. { - type: 'control_if', - message0: '%{BKY_CONTROLS_IF_MSG_IF} %1', - args0: [ + "type": "controls_ifelse", + "message0": "%{BKY_CONTROLS_IF_MSG_IF} %1", + "args0": [ { - type: 'input_value', - name: 'IF0', - check: 'Boolean' + "type": "input_value", + "name": "IF0", + "check": "Boolean" } ], - message1: '%{BKY_CONTROLS_IF_MSG_THEN} %1', - args1: [ + "message1": "%{BKY_CONTROLS_IF_MSG_THEN} %1", + "args1": [ { - type: 'input_statement', - name: 'DO0' + "type": "input_statement", + "name": "DO0" } ], - previousStatement: null, - nextStatement: null, - colour: '#b063c5', - tooltip: '%{BKYCONTROLS_IF_TOOLTIP_2}', - helpUrl: '%{BKY_CONTROLS_IF_HELPURL}', - extensions: ['controls_if_tooltip'] + "message2": "%{BKY_CONTROLS_IF_MSG_ELSE} %1", + "args2": [ + { + "type": "input_statement", + "name": "ELSE" + } + ], + "previousStatement": null, + "nextStatement": null, + "style": "logic_blocks", + "tooltip": "%{BKYCONTROLS_IF_TOOLTIP_2}", + "helpUrl": "%{BKY_CONTROLS_IF_HELPURL}", + "extensions": ["controls_if_tooltip"] }, + // Block for comparison operator. { - type: 'controls_ifelse', - message0: '%{BKY_CONTROLS_IF_MSG_IF} %1', - args0: [ + "type": "logic_compare", + "message0": "%1 %2 %3", + "args0": [ { - type: 'input_value', - name: 'IF0', - check: 'Boolean' + "type": "input_value", + "name": "A" + }, + { + "type": "field_dropdown", + "name": "OP", + "options": [ + ["=", "EQ"], + ["\u2260", "NEQ"], + ["\u200F<", "LT"], + ["\u200F\u2264", "LTE"], + ["\u200F>", "GT"], + ["\u200F\u2265", "GTE"] + ] + }, + { + "type": "input_value", + "name": "B" } ], - message1: '%{BKY_CONTROLS_IF_MSG_THEN} %1', - args1: [ + "inputsInline": true, + "output": "Boolean", + "style": "logic_blocks", + "helpUrl": "%{BKY_LOGIC_COMPARE_HELPURL}", + "extensions": ["logic_compare", "logic_op_tooltip"] + }, + // Block for logical operations: 'and', 'or'. + { + "type": "logic_operation", + "message0": "%1 %2 %3", + "args0": [ { - type: 'input_statement', - name: 'DO0' + "type": "input_value", + "name": "A", + "check": "Boolean" + }, + { + "type": "field_dropdown", + "name": "OP", + "options": [ + ["%{BKY_LOGIC_OPERATION_AND}", "AND"], + ["%{BKY_LOGIC_OPERATION_OR}", "OR"] + ] + }, + { + "type": "input_value", + "name": "B", + "check": "Boolean" } ], - message2: '%{BKY_CONTROLS_IF_MSG_ELSE} %1', - args2: [ + "inputsInline": true, + "output": "Boolean", + "style": "logic_blocks", + "helpUrl": "%{BKY_LOGIC_OPERATION_HELPURL}", + "extensions": ["logic_op_tooltip"] + }, + // Block for negation. + { + "type": "logic_negate", + "message0": "%{BKY_LOGIC_NEGATE_TITLE}", + "args0": [ { - type: 'input_statement', - name: 'ELSE' + "type": "input_value", + "name": "BOOL", + "check": "Boolean" } ], - previousStatement: null, - nextStatement: null, - colour: '#b063c5', - tooltip: '%{BKYCONTROLS_IF_TOOLTIP_2}', - helpUrl: '%{BKY_CONTROLS_IF_HELPURL}', - extensions: ['controls_if_tooltip'] + "output": "Boolean", + "style": "logic_blocks", + "tooltip": "%{BKY_LOGIC_NEGATE_TOOLTIP}", + "helpUrl": "%{BKY_LOGIC_NEGATE_HELPURL}" + }, + // Block for null data type. + { + "type": "logic_null", + "message0": "%{BKY_LOGIC_NULL}", + "output": null, + "style": "logic_blocks", + "tooltip": "%{BKY_LOGIC_NULL_TOOLTIP}", + "helpUrl": "%{BKY_LOGIC_NULL_HELPURL}" + }, + // Block for ternary operator. + { + "type": "logic_ternary", + "message0": "%{BKY_LOGIC_TERNARY_CONDITION} %1", + "args0": [ + { + "type": "input_value", + "name": "IF", + "check": "Boolean" + } + ], + "message1": "%{BKY_LOGIC_TERNARY_IF_TRUE} %1", + "args1": [ + { + "type": "input_value", + "name": "THEN" + } + ], + "message2": "%{BKY_LOGIC_TERNARY_IF_FALSE} %1", + "args2": [ + { + "type": "input_value", + "name": "ELSE" + } + ], + "output": null, + "style": "logic_blocks", + "tooltip": "%{BKY_LOGIC_TERNARY_TOOLTIP}", + "helpUrl": "%{BKY_LOGIC_TERNARY_HELPURL}", + "extensions": ["logic_ternary"] } -]); \ No newline at end of file +]); // END JSON EXTRACT (Do not delete this comment.) + +Blockly.defineBlocksWithJsonArray([ // Mutator blocks. Do not extract. + // Block representing the if statement in the controls_if mutator. + { + "type": "controls_if_if", + "message0": "%{BKY_CONTROLS_IF_IF_TITLE_IF}", + "nextStatement": null, + "enableContextMenu": false, + "style": "logic_blocks", + "tooltip": "%{BKY_CONTROLS_IF_IF_TOOLTIP}" + }, + // Block representing the else-if statement in the controls_if mutator. + { + "type": "controls_if_elseif", + "message0": "%{BKY_CONTROLS_IF_ELSEIF_TITLE_ELSEIF}", + "previousStatement": null, + "nextStatement": null, + "enableContextMenu": false, + "style": "logic_blocks", + "tooltip": "%{BKY_CONTROLS_IF_ELSEIF_TOOLTIP}" + }, + // Block representing the else statement in the controls_if mutator. + { + "type": "controls_if_else", + "message0": "%{BKY_CONTROLS_IF_ELSE_TITLE_ELSE}", + "previousStatement": null, + "enableContextMenu": false, + "style": "logic_blocks", + "tooltip": "%{BKY_CONTROLS_IF_ELSE_TOOLTIP}" + } +]); + + + diff --git a/src/components/Blockly/blocks/math.js b/src/components/Blockly/blocks/math.js new file mode 100644 index 0000000..49bdf7d --- /dev/null +++ b/src/components/Blockly/blocks/math.js @@ -0,0 +1,2 @@ + +import Blockly from 'blockly'; \ No newline at end of file diff --git a/src/components/Blockly/blocks/procedures.js b/src/components/Blockly/blocks/procedures.js new file mode 100644 index 0000000..5bd6214 --- /dev/null +++ b/src/components/Blockly/blocks/procedures.js @@ -0,0 +1,38 @@ +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Block for the Arduino functions. + * The Arduino built in functions syntax can be found at: + * https://arduino.cc/en/Reference/HomePage + */ + +import * as Blockly from 'blockly/core'; +import { getColour } from '../helpers/colour'; + + +Blockly.Blocks['arduino_functions'] = { + /** + * Block for defining the Arduino setup() and loop() functions. + * @this Blockly.Block + */ + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_FUN_RUN_SETUP); + this.appendStatementInput('SETUP_FUNC'); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_FUN_RUN_LOOP); + this.appendStatementInput('LOOP_FUNC'); + this.setInputsInline(false); + this.setColour(getColour().procedures); + this.setTooltip(Blockly.Msg.ARD_FUN_RUN_TIP); + this.setHelpUrl('https://arduino.cc/en/Reference/Loop'); + this.contextMenu = false; + }, + /** @return {!boolean} True if the block instance is in the workspace. */ + getArduinoLoopsInstance: function () { + return true; + } +}; diff --git a/src/components/Blockly/blocks/sensebox-display.js b/src/components/Blockly/blocks/sensebox-display.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Blockly/blocks/sensebox-osem.js b/src/components/Blockly/blocks/sensebox-osem.js new file mode 100644 index 0000000..a6f4eaf --- /dev/null +++ b/src/components/Blockly/blocks/sensebox-osem.js @@ -0,0 +1,114 @@ +import * as Blockly from 'blockly/core'; +import { getColour } from '../helpers/colour'; +import Block from 'blockly' + + +Blockly.Blocks['sensebox_osem_connection'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_osem_connection_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_osem_connection) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_osem_host, '"ingress.opensensemap.org"'], [Blockly.Msg.senseBox_osem_host_workshop, '"ingress.workshop.opensensemap.org"']]), "host") + .appendField('SSL') + .appendField(new Blockly.FieldCheckbox("TRUE"), "SSL"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_osem_exposure) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_osem_stationary, 'Stationary'], [Blockly.Msg.senseBox_osem_mobile, 'Mobile']]), "type"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField("senseBox ID") + .appendField(new Blockly.FieldTextInput("senseBox ID"), "BoxID"); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.senseBox_sensor) + .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + onchange: function (e) { + var block = this; + var blocks = block.getDescendants() + //Blockly.Blocks.sensebox.getDescendants = blocks; + + }, + mutationToDom: function () { + var container = document.createElement('mutation'); + var input = this.getFieldValue('type'); + this.updateShape_(input); + container.setAttribute('type', input); + return container; + }, + + domToMutation: function (xmlElement) { + var connections = xmlElement.getAttribute('connections'); + this.updateShape_(connections); + }, + /** + * Modify this block to have the correct number of pins available. + * @param {boolean} + * @private + * @this Blockly.Block + */ + updateShape_: function () { + var extraFieldExist = this.getFieldValue('gps'); + var input = this.getFieldValue('type'); + if ((input == 'Mobile') && extraFieldExist == null) { + this.appendValueInput('lat', 'Number') + .appendField(Blockly.Msg.senseBox_gps_lat, 'gps'); + this.appendValueInput('lng', 'Number') + .appendField(Blockly.Msg.senseBox_gps_lng); + this.appendValueInput('altitude', 'Number') + .appendField(Blockly.Msg.senseBox_gps_alt); + this.appendValueInput('timeStamp', 'Number') + .appendField(Blockly.Msg.senseBox_gps_timeStamp); + } + + if (input == 'Stationary' && extraFieldExist != null) { + this.removeInput('lat'); + this.removeInput('lng'); + this.removeInput('altitude'); + this.removeInput('timeStamp'); + } + }, +}; +Blockly.Blocks['sensebox_send_to_osem'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_send_to_osem_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_send_to_osem); + this.appendValueInput('Value') + .setCheck(null) + .appendField('Sensor ID') + .appendField(new Blockly.FieldTextInput('Sensor ID'), 'SensorID'); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if block is not nested inside a the correct loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) != -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + LOOP_TYPES: ['sensebox_osem_connection'], +}; \ No newline at end of file diff --git a/src/components/Blockly/blocks/sensebox-sensors.js b/src/components/Blockly/blocks/sensebox-sensors.js index 692ad52..8c1c24b 100644 --- a/src/components/Blockly/blocks/sensebox-sensors.js +++ b/src/components/Blockly/blocks/sensebox-sensors.js @@ -1,5 +1,12 @@ import Blockly from 'blockly'; +import { getColour } from '../helpers/colour' +import * as Types from '../helpers/types' +import { selectedBoard } from '../helpers/board' +/** + * HDC1080 Temperature and Humidity Sensor + * + */ Blockly.Blocks['sensebox_sensor_temp_hum'] = { init: function () { @@ -9,12 +16,297 @@ Blockly.Blocks['sensebox_sensor_temp_hum'] = { .setAlign(Blockly.ALIGN_RIGHT) .appendField(Blockly.Msg.senseBox_value) .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_temp, "Temperature"], [Blockly.Msg.senseBox_hum, "Humidity"]]), "NAME"); - this.setOutput(true, "Number"); - this.setColour(120); + this.setOutput(true, Types.NUMBER.typeId); + this.setColour(getColour().sensebox); this.setTooltip(Blockly.Msg.senseBox_temp_hum_tip); this.setHelpUrl('https://edu.books.sensebox.de/de/projekte/diy_umweltstation/temp_und_luftfeuchte.html'); }, getBlockType: function () { return Blockly.Types.DECIMAL; }, -}; \ No newline at end of file +}; + +/** + * VEML6070 and TSL4513 + * + */ + + +Blockly.Blocks['sensebox_sensor_uv_light'] = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_uv_light); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.senseBox_value) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_light, "Illuminance"], [Blockly.Msg.senseBox_uv, "UvIntensity"]]), "NAME"); + this.setOutput(true, Types.NUMBER.typeId); + this.setColour(getColour().sensebox); + this.setTooltip(Blockly.Msg.senseBox_uv_light_tip); + this.setHelpUrl('https://edu.books.sensebox.de/de/projekte/diy_umweltstation/temp_und_luftfeuchte.html'); + }, + getBlockType: function () { + return Blockly.Types.DECIMAL; + }, +}; + +/* +BMX055 Three differen Blocks for Accelerometer, Gyroscope, Compass +*/ + +Blockly.Blocks['sensebox_sensor_bmx055_accelerometer'] = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_bmx055_accelerometer); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_bmx055_accelerometer_direction) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_bmx055_accelerometer_direction_x, "X"], [Blockly.Msg.senseBox_bmx055_accelerometer_direction_y, "Y"], [Blockly.Msg.senseBox_bmx055_accelerometer_direction_z, "Z"], [Blockly.Msg.senseBox_bmx055_accelerometer_direction_total, "Total"]]), "VALUE"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_bmx055_accelerometer_range) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_bmx055_accelerometer_range_2g, "0x3"], [Blockly.Msg.senseBox_bmx055_accelerometer_range_4g, "0x5"], [Blockly.Msg.senseBox_bmx055_accelerometer_range_8g, "0x8"], [Blockly.Msg.senseBox_bmx055_accelerometer_range_16g, "0x0C"]]), "RANGE"); + this.setOutput(true, Types.NUMBER.typeId); + this.setColour(getColour().sensebox); + this.setTooltip(Blockly.Msg.senseBox_bmx055_accelerometer_tip); + this.setHelpUrl('https://edu.books.sensebox.de/de/projekte/diy_umweltstation/temp_und_luftfeuchte.html'); + }, + getBlockType: function () { + return Types.NUMBER.typeId; + }, +}; + +/** + * SDS011 Fine Particular Matter Sensor + * + */ + +Blockly.Blocks['sensebox_sensor_sds011'] = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_sds011); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.senseBox_value) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_sds011_pm25, "Pm25"], [Blockly.Msg.senseBox_sds011_pm10, "Pm10"]]), "NAME") + .appendField(Blockly.Msg.senseBox_sds011_dimension) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_sds011_serial1, "Serial1"], [Blockly.Msg.senseBox_sds011_serial2, "Serial2"]]), "SERIAL"); + this.setOutput(true, Types.NUMBER.typeId); + this.setColour(getColour().sensebox); + this.setTooltip(Blockly.Msg.senseBox_sds011_tip); + this.setHelpUrl('https://edu.books.sensebox.de/de/projekte/diy_umweltstation/temp_und_luftfeuchte.html'); + }, + getBlockType: function () { + return Blockly.Types.DECIMAL; + }, +}; + + +/** + * BMP280 Pressure Sensor + * + */ + +Blockly.Blocks['sensebox_sensor_pressure'] = { + init: function () { + var dropdownOptions = [[Blockly.Msg.senseBox_pressure, "Pressure"], [Blockly.Msg.senseBox_temp, "Temperature"], [Blockly.Msg.senseBox_gps_alt, "Altitude"]]; + var dropdown = new Blockly.FieldDropdown(dropdownOptions, function (option) { + var input = (option == 'Pressure') || (option == 'Temperature') || (option == 'Altitude'); + this.sourceBlock_.updateShape_(input); + }); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_pressure_sensor); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.senseBox_value) + .appendField(dropdown, "NAME"); + this.setColour(getColour().sensebox); + this.setOutput(true, Types.NUMBER.typeId); + this.setTooltip(Blockly.Msg.senseBox_pressure_tip); + this.setHelpUrl('https://edu.books.sensebox.de/de/projekte/diy_umweltstation/luftdruck.html'); + }, + /** + * Parse XML to restore the number of pins available. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + + domToMutation: function (xmlElement) { + var input = (xmlElement.getAttribute('port')); + + }, + /** + * Create XML to represent number of pins selection. + * @return {!Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + var input = this.getFieldValue('NAME'); + this.updateShape_(input); + container.setAttribute('NAME', input); + return container; + }, + /** + * Modify this block to have the correct number of pins available. + * @param {boolean} + * @private + * @this Blockly.Block + */ + updateShape_: function () { + var extraFieldExist = this.getFieldValue('referencePressure'); + var input = this.getFieldValue('NAME'); + if (input == 'Altitude' && extraFieldExist == null) { + this.appendDummyInput('extraField') + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.senseBox_pressure_referencePressure) + .appendField(new Blockly.FieldTextInput("1013"), "referencePressure") + .appendField(Blockly.Msg.senseBox_pressure_referencePressure_dim); + } + + if ((input == 'Pressure' || input == 'Temperature') && extraFieldExist != null) { + this.removeInput('extraField'); + } + }, + getBlockType: function () { + var input = this.getFieldValue('NAME'); + if (input == 'Temperature') { + return Types.DECIMAL.typeId; + } else { + return Types.LARGE_NUMBER.typeId; + } + }, +}; + + +/** + * BME680 Environmental Sensor + * + */ + +Blockly.Blocks['sensebox_sensor_bme680_bsec'] = { + init: function () { + var dropdownOptions = [[Blockly.Msg.senseBox_temp, "temperature"], [Blockly.Msg.senseBox_hum, "humidity"], [Blockly.Msg.senseBox_pressure, "pressure"], [Blockly.Msg.senseBox_bme_iaq, "IAQ"], [Blockly.Msg.senseBox_bme_iaq_accuracy, "IAQAccuracy"], [Blockly.Msg.senseBox_bme_co2, "CO2"], [Blockly.Msg.senseBox_bme_breatheVocEquivalent, "breathVocEquivalent"]]; + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_bme680); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.senseBox_value) + .appendField(new Blockly.FieldDropdown(dropdownOptions), "dropdown") + this.setOutput(true, Types.NUMBER.typeId); + this.setColour(getColour().sensebox); + this.setTooltip(Blockly.Msg.senseBox_bme_tip); + }, + getBlockType: function () { + return Types.DECIMAL.typeId; + }, +}; + +/** + * Ultrasonic Sensor + * + * + */ + + +Blockly.Blocks['sensebox_sensor_ultrasonic_ranger'] = { + init: function () { + + var dropdownOptions = [[Blockly.Msg.senseBox_ultrasonic_port_A, 'A'], + [Blockly.Msg.senseBox_ultrasonic_port_B, 'B'], [Blockly.Msg.senseBox_ultrasonic_port_C, 'C']]; + var dropdown = new Blockly.FieldDropdown(dropdownOptions, function (option) { + var input = (option == 'A') || (option == 'B') || (option == 'C'); + this.sourceBlock_.updateShape_(input); + }); + + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_ultrasonic) + .appendField(dropdown, "port"); + this.appendDummyInput('TrigEcho') + .setAlign(Blockly.ALIGN_RIGHT) + .appendField(Blockly.Msg.senseBox_ultrasonic_trigger) + .appendField(new Blockly.FieldDropdown( + selectedBoard().digitalPins), 'ultrasonic_trigger') + .appendField(Blockly.Msg.senseBox_ultrasonic_echo) + .appendField(new Blockly.FieldDropdown( + selectedBoard().digitalPins), 'ultrasonic_echo'); + this.setOutput(true, Types.NUMBER.typeId); + this.setTooltip(Blockly.Msg.senseBox_ultrasonic_tip); + this.setHelpUrl('https://sensebox.de/books'); + }, + /** + * Parse XML to restore the number of pins available. + * @param {!Element} xmlElement XML storage element. + * @this Blockly.Block + */ + domToMutation: function (xmlElement) { + var input = (xmlElement.getAttribute('port')); + + }, + /** + * Create XML to represent number of pins selection. + * @return {!Element} XML storage element. + * @this Blockly.Block + */ + mutationToDom: function () { + var container = document.createElement('mutation'); + var input = this.getFieldValue('port'); + this.updateShape_(input); + container.setAttribute("port", input); + return container; + }, + /** + * Modify this block to have the correct number of pins available. + * @param {boolean} + * @private + * @this Blockly.Block + */ + updateShape_: function () { + var input = this.getFieldValue('port'); + switch (input) { + case 'A': + this.setFieldValue('1', 'ultrasonic_trigger'); + this.setFieldValue('2', 'ultrasonic_echo'); + break; + case 'B': + this.setFieldValue('3', 'ultrasonic_trigger'); + this.setFieldValue('4', 'ultrasonic_echo'); + break; + case 'C': + this.setFieldValue('5', 'ultrasonic_trigger'); + this.setFieldValue('6', 'ultrasonic_echo'); + break; + } + }, + + getBlockType: function () { + return Blockly.Types.NUMBER; + } +}; + + +/** + * Microphone + * + */ + +Blockly.Blocks['sensebox_sensor_sound'] = { + init: function () { + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_sound) + .appendField("Pin:") + .appendField(new Blockly.FieldDropdown(selectedBoard().analogPins), "PIN") + this.setOutput(true, Types.NUMBER.typeId); + this.setHelpUrl(Blockly.Msg.senseBox_sound_tip); + this.setTooltip('Dieser Sensor mist den Geräuschpegel.'); + }, + getBlockType: function () { + return Types.NUMBER.typeId; + }, +}; + + + + diff --git a/src/components/Blockly/blocks/sensebox-telegram.js b/src/components/Blockly/blocks/sensebox-telegram.js index 2ba704d..ed4042c 100644 --- a/src/components/Blockly/blocks/sensebox-telegram.js +++ b/src/components/Blockly/blocks/sensebox-telegram.js @@ -1,8 +1,10 @@ import Blockly from 'blockly'; +import { getColour } from '../helpers/colour' + Blockly.Blocks["sensebox_telegram"] = { init: function () { - this.setColour(120); + this.setColour(getColour().sensebox); this.appendDummyInput() .appendField(Blockly.Msg.senseBox_telegram_init); this.appendDummyInput() @@ -15,3 +17,37 @@ Blockly.Blocks["sensebox_telegram"] = { }; +Blockly.Blocks["sensebox_telegram_do"] = { + init: function () { + this.setColour(getColour().sensebox); + this.appendDummyInput().appendField(Blockly.Msg.senseBox_telegram_do); + this.appendStatementInput("telegram_do"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +Blockly.Blocks["sensebox_telegram_do_on_message"] = { + init: function () { + this.setColour(getColour().sensebox); + this.appendDummyInput().appendField(Blockly.Msg.senseBox_telegram_do_on_message); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_telegram_message) + .appendField(new Blockly.FieldTextInput("/message"), 'telegram_message'); + this.appendStatementInput("telegram_do_on_message").setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +Blockly.Blocks["sensebox_telegram_send"] = { + init: function () { + this.setColour(getColour().sensebox); + this.appendDummyInput().appendField(Blockly.Msg.senseBox_telegram_send); + this.appendValueInput("telegram_text_to_send").setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ["sensebox_telegram_do_on_message"] +}; \ No newline at end of file diff --git a/src/components/Blockly/blocks/time.js b/src/components/Blockly/blocks/time.js new file mode 100644 index 0000000..248fe88 --- /dev/null +++ b/src/components/Blockly/blocks/time.js @@ -0,0 +1,130 @@ +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Blocks for Arduino Time functions. + * The arduino built in functions syntax can be found in + * http://arduino.cc/en/Reference/HomePage + */ +import Blockly from 'blockly'; +import { getColour } from '../helpers/colour' +import * as Types from '../helpers/types' + + +Blockly.Blocks['time_delay'] = { + /** + * Delay block definition + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/Delay'); + this.setColour(getColour().time); + this.appendValueInput('DELAY_TIME_MILI') + .setCheck(Types.NUMBER.checkList) + .appendField(Blockly.Msg.ARD_TIME_DELAY); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_TIME_MS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_TIME_DELAY_TIP); + } +}; + +Blockly.Blocks['time_delaymicros'] = { + /** + * delayMicroseconds block definition + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/DelayMicroseconds'); + this.setColour(getColour().time); + this.appendValueInput('DELAY_TIME_MICRO') + .setCheck(Types.NUMBER.checkList) + .appendField(Blockly.Msg.ARD_TIME_DELAY); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_TIME_DELAY_MICROS); + this.setInputsInline(true); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.ARD_TIME_DELAY_MICRO_TIP); + } +}; + +Blockly.Blocks['time_millis'] = { + /** + * Elapsed time in milliseconds block definition + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/Millis'); + this.setColour(getColour().time); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_TIME_MILLIS); + this.setOutput(true, Types.LARGE_NUMBER.typeId); + this.setTooltip(Blockly.Msg.ARD_TIME_MILLIS_TIP); + }, + /** @return {string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Blockly.Types.LARGE_NUMBER; + } +}; + +Blockly.Blocks['time_micros'] = { + /** + * Elapsed time in microseconds block definition + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/Micros'); + this.setColour(getColour().time); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_TIME_MICROS); + this.setOutput(true, Types.LARGE_NUMBER.typeId); + this.setTooltip(Blockly.Msg.ARD_TIME_MICROS_TIP); + }, + /** + * Should be a long (32bit), but for for now an int. + * @return {string} The type of return value for the block, an integer. + */ + getBlockType: function () { + return Types.LARGE_NUMBER; + } +}; + +Blockly.Blocks['infinite_loop'] = { + /** + * Waits forever, end of program. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl(''); + this.setColour(getColour().time); + this.appendDummyInput() + .appendField(Blockly.Msg.ARD_TIME_INF); + this.setInputsInline(true); + this.setPreviousStatement(true); + this.setTooltip(Blockly.Msg.ARD_TIME_INF_TIP); + } +}; + +Blockly.Blocks['sensebox_interval_timer'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_interval_timer_tip); + this.setInputsInline(true); + this.setHelpUrl(''); + this.setColour(getColour().time); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_interval_timer); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(new Blockly.FieldTextInput("10000"), "interval") + .appendField(Blockly.Msg.senseBox_interval); + this.appendStatementInput('DO') + .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; diff --git a/src/components/Blockly/generator/generator.js b/src/components/Blockly/generator/generator.js index 24b5473..89cd398 100644 --- a/src/components/Blockly/generator/generator.js +++ b/src/components/Blockly/generator/generator.js @@ -81,6 +81,19 @@ Blockly['Arduino'].ORDER_ASSIGNMENT = 14; // = *= /= ~/= %= += -= <<= >>= &= ^= Blockly['Arduino'].ORDER_COMMA = 18; // , Blockly['Arduino'].ORDER_NONE = 99; // (...) + + + +/** + * + * @param {} workspace + * + * Blockly Types + */ + + + + /** * Initialise the database of variable names. * @param {!Blockly.Workspace} workspace Workspace to generate code from. @@ -89,9 +102,17 @@ Blockly['Arduino'].init = function (workspace) { // Create a dictionary of definitions to be printed before the code. Blockly['Arduino'].libraries_ = Object.create(null); + Blockly['Arduino'].definitions_ = Object.create(null); + // creates a list of code to be setup before the setup block Blockly['Arduino'].setupCode_ = Object.create(null); + // creates a list of code for the loop to be runned once + Blockly['Arduino'].loopCodeOnce_ = Object.create(null) + + // creates a list of code variables + Blockly['Arduino'].variables_ = Object.create(null) + // Create a dictionary mapping desired function names in definitions_ // to actual function names (to avoid collisions with user functions). Blockly['Arduino'].functionNames_ = Object.create(null); @@ -172,39 +193,42 @@ Blockly['Arduino'].init = function (workspace) { */ Blockly['Arduino'].finish = function (code) { let libraryCode = ''; + let variablesCode = '' let functionsCode = ''; + let definitionsCode = ''; + let loopCodeOnce = ''; + let setupCode = ''; + let preSetupCode = ''; let devVariables = '\n'; for (const key in Blockly['Arduino'].libraries_) { libraryCode += Blockly['Arduino'].libraries_[key] + '\n'; } + for (const key in Blockly['Arduino'].variables_) { + variablesCode += Blockly['Arduino'].variables_[key] + '\n'; + } + + for (const key in Blockly['Arduino'].definitions_) { + definitionsCode += Blockly['Arduino'].definitions_[key] + '\n'; + } + + for (const key in Blockly['Arduino'].loopCodeOnce_) { + loopCodeOnce += Blockly['Arduino'].loopCodeOnce_[key] + '\n'; + } + for (const key in Blockly['Arduino'].functionNames_) { functionsCode += Blockly['Arduino'].functionNames_[key] + '\n'; } - if (!_.isEmpty(Blockly['Arduino'].setupCode_['bluetooth_setup'])) { - devVariables += 'String bluetoothMessageDEV = ""; \n'; - } - if (!_.isEmpty(Blockly['Arduino'].setupCode_['serial_begin'])) { - devVariables += 'String serialMessageDEV = ""; \n'; - } - - if (!_.isEmpty(Blockly['Arduino'].functionNames_['double_to_string_debug'])) { - devVariables += 'boolean stopDebugging = false; \n'; - } - - let setupCode = ''; - - let preSetupCode = ''; for (const key in Blockly['Arduino'].setupCode_) { preSetupCode += Blockly['Arduino'].setupCode_[key] || ''; } setupCode = '\nvoid setup() { \n' + preSetupCode + '\n}\n'; - let loopCode = '\nvoid loop() { \n' + code + '\n}\n'; + let loopCode = '\nvoid loop() { \n' + loopCodeOnce + code + '\n}\n'; // Convert the definitions dictionary into a list. @@ -213,6 +237,10 @@ Blockly['Arduino'].finish = function (code) { '\n' + libraryCode + '\n' + + variablesCode + + '\n' + + definitionsCode + + '\n' + Blockly['Arduino'].variablesInitCode_ + '\n' + functionsCode + @@ -225,6 +253,7 @@ Blockly['Arduino'].finish = function (code) { // Clean up temporary data. delete Blockly['Arduino'].definitions_; delete Blockly['Arduino'].functionNames_; + delete Blockly['Arduino'].loopCodeOnce_; delete Blockly['Arduino'].variablesInitCode_; delete Blockly['Arduino'].libraries_; Blockly['Arduino'].variableDB_.reset(); diff --git a/src/components/Blockly/generator/index.js b/src/components/Blockly/generator/index.js index c629df3..263f970 100644 --- a/src/components/Blockly/generator/index.js +++ b/src/components/Blockly/generator/index.js @@ -1,7 +1,12 @@ import './generator'; import './loops'; -import './sensebox'; +import './sensebox-sensors'; +import './sensebox-telegram'; +import './sensebox-osem'; import './logic'; import './math'; import './io'; +import './procedures'; +import './time'; + diff --git a/src/components/Blockly/generator/io.js b/src/components/Blockly/generator/io.js index 5cef62a..19cc7b2 100644 --- a/src/components/Blockly/generator/io.js +++ b/src/components/Blockly/generator/io.js @@ -30,3 +30,86 @@ Blockly.Arduino['io_digitalread'] = function (block) { var code = 'digitalRead(' + pin + ')'; return [code, Blockly.Arduino.ORDER_ATOMIC]; }; + + +/** + * Function for setting the state (Y) of a built-in LED (X). + * Arduino code: setup { pinMode(X, OUTPUT); } + * loop { digitalWrite(X, Y); } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['io_builtin_led'] = function (block) { + var pin = block.getFieldValue('BUILT_IN_LED'); + var stateOutput = Blockly.Arduino.valueToCode( + block, 'STATE', Blockly.Arduino.ORDER_ATOMIC) || 'LOW'; + Blockly['Arduino'].setupCode_['pinMode' + pin] = 'pindMode(' + pin + 'OUTPUT);' + var code = 'digitalWrite(' + pin + ', ' + stateOutput + ');\n'; + return code; +}; + + +/** + * Function for setting the state (Y) of an analogue output (X). + * Arduino code: setup { pinMode(X, OUTPUT); } + * loop { analogWrite(X, Y); } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['io_analogwrite'] = function (block) { + var pin = block.getFieldValue('PIN'); + var stateOutput = Blockly.Arduino.valueToCode( + block, 'NUM', Blockly.Arduino.ORDER_ATOMIC) || '0'; + Blockly['Arduino'].setupCode_['pinMode' + pin] = 'pinMode(' + pin + ', OUTPUT);'; + // Warn if the input value is out of range + if ((stateOutput < 0) || (stateOutput > 255)) { + block.setWarningText('The analogue value set must be between 0 and 255', + 'pwm_value'); + } else { + block.setWarningText(null, 'pwm_value'); + } + var code = 'analogWrite(' + pin + ', ' + stateOutput + ');\n'; + return code; +}; + +/** + * Function for reading an analogue pin value (X). + * Arduino code: setup { pinMode(X, INPUT); } + * loop { analogRead(X) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['io_analogread'] = function (block) { + var pin = block.getFieldValue('PIN'); + Blockly['Arduino'].setupCode_['pinMode' + pin] = 'pinMode(' + pin + ', INPUT);'; + var code = 'analogRead(' + pin + ')'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * Value for defining a digital pin state. + * Arduino code: loop { HIGH / LOW } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['io_highlow'] = function (block) { + var code = block.getFieldValue('STATE'); + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +Blockly.Arduino['io_pulsein'] = function (block) { + var pin = block.getFieldValue("PULSEPIN"); + var type = Blockly.Arduino.valueToCode(block, "PULSETYPE", Blockly.Arduino.ORDER_ATOMIC); + Blockly['Arduino'].setupCode_['pinMode' + pin] = 'pinMode(' + pin + ', INPUT);'; + var code = 'pulseIn(' + pin + ', ' + type + ')'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +Blockly.Arduino['io_pulsetimeout'] = function (block) { + var pin = block.getFieldValue("PULSEPIN"); + var type = Blockly.Arduino.valueToCode(block, "PULSETYPE", Blockly.Arduino.ORDER_ATOMIC); + var timeout = Blockly.Arduino.valueToCode(block, "TIMEOUT", Blockly.Arduino.ORDER_ATOMIC); + Blockly['Arduino'].setupCode_['pinMode' + pin] = 'pinMode(' + pin + ', INPUT);'; + var code = 'pulseIn(' + pin + ', ' + type + ', ' + timeout + ')'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; diff --git a/src/components/Blockly/generator/logic.js b/src/components/Blockly/generator/logic.js index ac6b7a5..402a020 100644 --- a/src/components/Blockly/generator/logic.js +++ b/src/components/Blockly/generator/logic.js @@ -55,7 +55,7 @@ Blockly.Arduino['logic_operation'] = function (Block) { return [code, order]; }; -Blockly.Arduino['control_if'] = function (Block) { +Blockly.Arduino['controls_if'] = function (Block) { // If/elseif/else condition. let n = 0; let code = '', diff --git a/src/components/Blockly/generator/procedures.js b/src/components/Blockly/generator/procedures.js new file mode 100644 index 0000000..92e57a7 --- /dev/null +++ b/src/components/Blockly/generator/procedures.js @@ -0,0 +1,30 @@ +import * as Blockly from 'blockly/core'; +import { Block } from 'blockly'; + +/** + * Code generator to add code into the setup() and loop() functions. + * Its use is not mandatory, but necessary to add manual code to setup(). + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['arduino_functions'] = function (block) { + // Edited version of Blockly.Generator.prototype.statementToCode + function statementToCodeNoTab(block, name) { + var targetBlock = block.getInputTargetBlock(name); + var code = Blockly.Arduino.blockToCode(targetBlock); + if (typeof code != 'string') { + throw 'Expecting code from statement block "' + targetBlock.type + '".'; + } + return code; + } + + var setupBranch = Blockly.Arduino.statementToCode(block, 'SETUP_FUNC'); + //var setupCode = Blockly.Arduino.scrub_(block, setupBranch); No comment block + if (setupBranch) { + Blockly.Arduino.setupCode_('userSetupCode', setupBranch, true); + } + + var loopBranch = statementToCodeNoTab(block, 'LOOP_FUNC'); + //var loopcode = Blockly.Arduino.scrub_(block, loopBranch); No comment block + return loopBranch; +}; diff --git a/src/components/Blockly/generator/sensebox-osem.js b/src/components/Blockly/generator/sensebox-osem.js new file mode 100644 index 0000000..ee19a76 --- /dev/null +++ b/src/components/Blockly/generator/sensebox-osem.js @@ -0,0 +1,178 @@ +import Blockly, { Blocks } from 'blockly'; +import { getColour } from '../helpers/colour' +import Block from 'blockly'; + + +/** +* Block send Data to the openSenseMap +*/ +Blockly.Arduino.sensebox_send_to_osem = function (block) { + var code = ''; + var sensor_id = this.getFieldValue('SensorID'); + var id = sensor_id.slice(-3).toUpperCase(); + var sensor_value = Blockly.Arduino.valueToCode(this, 'Value', Blockly.Arduino.ORDER_ATOMIC) || '"Keine Eingabe"'; + Blockly.Arduino.definitions_['SENSOR_ID' + id + ''] = 'const char SENSOR_ID' + id + '[] PROGMEM = "' + sensor_id + '";'; + code += 'addMeasurement(SENSOR_ID' + id + ',' + sensor_value + ');\n'; + return code; +}; + +Blockly.Arduino.sensebox_osem_connection = function (Block) { + var box_id = this.getFieldValue('BoxID'); + var host = this.getFieldValue('host'); + var branch = Blockly.Arduino.statementToCode(Block, 'DO'); + var blocks = Blockly.Block.getDescendants; + var type = this.getFieldValue('type'); + var ssl = this.getFieldValue('SSL'); + var port = 0; + var count = 0; + // for (var i = 0; i < blocks.length; i++) { + // if (blocks[i].type === 'sensebox_send_to_osem') { + // count++; + + // } + // } + var num_sensors = count; + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['num_sensors'] = 'static const uint8_t NUM_SENSORS = ' + num_sensors + ';' + Blockly.Arduino.definitions_['SenseBoxID'] = 'const char SENSEBOX_ID [] PROGMEM = "' + box_id + '";'; + Blockly.Arduino.definitions_['host'] = 'const char server [] PROGMEM =' + host + ';'; + if (ssl == 'TRUE') { + Blockly.Arduino.definitions_['WiFiSSLClient'] = 'WiFiSSLClient client;'; + port = 443; + } else if (ssl == 'FALSE') { + Blockly.Arduino.definitions_['WiFiClient'] = 'WiFiClient client;'; + port = 80; + } + + Blockly.Arduino.definitions_['measurement'] = `typedef struct measurement { + const char *sensorId; + float value; + } measurement;`; + Blockly.Arduino.definitions_['buffer'] = 'char buffer[750];'; + Blockly.Arduino.definitions_['num_measurement'] = `measurement measurements[NUM_SENSORS]; + uint8_t num_measurements = 0;`; + Blockly.Arduino.definitions_['lengthMultiplikator'] = 'const int lengthMultiplikator = 35;'; + Blockly.Arduino.functionNames_['addMeasurement'] = ` + void addMeasurement(const char *sensorId, float value) { + measurements[num_measurements].sensorId = sensorId; + measurements[num_measurements].value = value; + num_measurements++; + }`; + if (type === 'Stationary') { + Blockly.Arduino.functionNames_['writeMeasurementsToClient'] = ` + void writeMeasurementsToClient() { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { + sprintf_P(buffer, PSTR("%s,%9.2f\\n"), measurements[i].sensorId, + measurements[i].value); + // transmit buffer to client + client.print(buffer); + } + // reset num_measurements + num_measurements = 0; + }`; + Blockly.Arduino.functionNames_['submitValues'] = ` + void submitValues() { + if (client.connected()) { + client.stop(); + delay(10); + } + bool connected = false; + char _server[strlen_P(server)]; + strcpy_P(_server, server); + for (uint8_t timeout = 2; timeout != 0; timeout--) { + Serial.println(F("connecting...")); + connected = client.connect(_server, `+ port + `); + if (connected == true) { + // construct the HTTP POST request: + sprintf_P(buffer, + PSTR("POST /boxes/%s/data HTTP/1.1\\nHost: %s\\nContent-Type: " + "text/csv\\nConnection: close\\nContent-Length: %i\\n\\n"), + SENSEBOX_ID, server, num_measurements * lengthMultiplikator); + // send the HTTP POST request: + client.print(buffer); + // send measurements + writeMeasurementsToClient(); + // send empty line to end the request + client.println(); + uint16_t timeout = 0; + // allow the response to be computed + while (timeout <= 5000) { + delay(10); + timeout = timeout + 10; + if (client.available()) { + break; + } + } + num_measurements = 0; + break; + } + } + }`; + var code = ''; + code += branch; + code += "submitValues();\n"; + } + else if (type === 'Mobile') { + var lat = Blockly.Arduino.valueToCode(Block, 'lat', Blockly.Arduino.ORDER_ATOMIC); + var lng = Blockly.Arduino.valueToCode(Block, 'lng', Blockly.Arduino.ORDER_ATOMIC); + var timestamp = Blockly.Arduino.valueToCode(Block, 'timeStamp', Blockly.Arduino.ORDER_ATOMIC); + var altitude = Blockly.Arduino.valueToCode(Block, 'altitude', Blockly.Arduino.ORDER_ATOMIC); + Blockly.Arduino.definitions_['lengthMultiplikator'] = 'const int lengthMultiplikator = 77;'; + Blockly.Arduino.functionNames_['writeMeasurementsToClient'] = ` + void writeMeasurementsToClient(float lat, float lng, float altitude, char* timeStamp) { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { + sprintf_P(buffer, PSTR("%s,%9.2f,%s,%3.6f,%3.6f,%5.2f\\n"), measurements[i].sensorId, + measurements[i].value, timeStamp, lng, lat, altitude); + // transmit buffer to client + client.print(buffer); + } + // reset num_measurements + num_measurements = 0; + }`; + Blockly.Arduino.functionNames_['submitValues'] = ` + void submitValues(float lat, float lng, float altitude, char* timeStamp) { + if (client.connected()) { + client.stop(); + delay(10); + } + bool connected = false; + char _server[strlen_P(server)]; + strcpy_P(_server, server); + for (uint8_t timeout = 2; timeout != 0; timeout--) { + Serial.println(F("connecting...")); + connected = client.connect(_server, `+ port + `); + if (connected == true) { + // construct the HTTP POST request: + sprintf_P(buffer, + PSTR("POST /boxes/%s/data HTTP/1.1\\nHost: %s\\nContent-Type: " + "text/csv\\nConnection: close\\nContent-Length: %i\\n\\n"), + SENSEBOX_ID, server, num_measurements * lengthMultiplikator); + // send the HTTP POST request: + client.print(buffer); + // send measurements + writeMeasurementsToClient(lat, lng, altitude, timeStamp); + // send empty line to end the request + client.println(); + uint16_t timeout = 0; + // allow the response to be computed + while (timeout <= 5000) { + delay(10); + timeout = timeout + 10; + if (client.available()) { + break; + } + } + + num_measurements = 0; + break; + } + } + }` + var code = ''; + code += branch; + code += 'submitValues(' + lat + ',' + lng + ',' + altitude + ',' + timestamp + ');\n'; + } + return code; +}; diff --git a/src/components/Blockly/generator/sensebox-sensors.js b/src/components/Blockly/generator/sensebox-sensors.js index ef5037c..e413075 100644 --- a/src/components/Blockly/generator/sensebox-sensors.js +++ b/src/components/Blockly/generator/sensebox-sensors.js @@ -1,6 +1,225 @@ -import * as Blockly from 'blockly/core'; -import { Block } from 'blockly'; +import Blockly from 'blockly'; +import { getColour } from '../helpers/colour'; +import { selectedBoard } from '../helpers/board'; -Blockly.Arduino['sensebox_telegram'] = function (Block) { +/** + * HDC1080 Temperature and Humidity Sensor + * + */ -}; \ No newline at end of file +Blockly.Arduino.sensebox_sensor_temp_hum = function () { + var dropdown_name = this.getFieldValue('NAME'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['define_hdc'] = 'HDC1080 hdc;'; + Blockly.Arduino.setupCode_['sensebox_sensor_temp_hum'] = 'hdc.begin();'; + var code = 'hdc.get' + dropdown_name + '()'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * VEML 6070 and TSL4513 UV-Light/Illuminance Sensor + * + */ + +Blockly.Arduino.sensebox_sensor_uv_light = function () { + var dropdown_name = this.getFieldValue('NAME'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + if (dropdown_name === 'UvIntensity') { + Blockly.Arduino.definitions_['define_veml'] = 'VEML6070 veml;' + Blockly.Arduino.setupCode_['sensebox_sensor_uv_light'] = 'veml.begin();' + var code = 'veml.get' + dropdown_name + '()'; + } + if (dropdown_name === 'Illuminance') { + Blockly.Arduino.definitions_['define_tsl'] = 'TSL45315 tsl;' + Blockly.Arduino.setupCode_['sensebox_sensor_illuminance'] = 'tsl.begin();' + var code = 'tsl.get' + dropdown_name + '()'; + } + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + + +/** + * BMX055 Accelerometer + * + */ + +Blockly.Arduino.sensebox_sensor_bmx055_accelerometer = function () { + var dropdown_value = this.getFieldValue('VALUE'); + var range = this.getFieldValue('RANGE'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['define_bmx'] = 'BMX055 bmx;'; + Blockly.Arduino.setupCode_['sensebox_sensor_bmx055'] = 'bmx.beginAcc(' + range + ');'; + var code = 'bmx.getAcceleration' + dropdown_value + '()'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * SDS011 Fine Particlar Matter + * + */ + +Blockly.Arduino.sensebox_sensor_sds011 = function () { + var dropdown_name = this.getFieldValue('NAME'); + var serial_name = this.getFieldValue('SERIAL'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.codeFunctions_['define_sds011'] = 'SDS011 my_sds(' + serial_name + ');'; + Blockly.Arduino.variables_['variables_sds011'] = 'float p10,p25;\n'; + Blockly.Arduino.setupCode_['sensebox_sensor_sds011'] = serial_name + '.begin(9600);'; + var code = 'my_sds.get' + dropdown_name + '()'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * BMP280 Pressure Sensor + * + */ + +Blockly.Arduino.sensebox_sensor_pressure = function () { + var dropdown_name = this.getFieldValue('NAME'); + var referencePressure = this.getFieldValue('referencePressure'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['define_pressure'] = 'BMP280 bmp_sensor;'; + Blockly.Arduino.setupCode_['sensebox_bmp_sensor'] = 'bmp_sensor.begin();'; + if (dropdown_name === 'Pressure' || dropdown_name == 'Temperature') { + var code = 'bmp_sensor.get' + dropdown_name + '()'; + } + else if (dropdown_name === 'Altitude') { + var code = 'bmp_sensor.getAltitude(' + referencePressure + ')'; + } + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + + +/** + * BME680 Environmental Sensor + * + */ + + +Blockly.Arduino.sensebox_sensor_bme680_bsec = function () { + var dropdown_name = this.getFieldValue('dropdown'); + Blockly.Arduino.libraries_['library_bsec'] = '#include "bsec.h"'; + Blockly.Arduino.definitions_['bsec_iaqSensor'] = 'Bsec iaqSensor;' + Blockly.Arduino.variables_['bmeTemperatur'] = 'float bmeTemperatur;'; + Blockly.Arduino.variables_['bmeHumidity'] = 'float bmeHumidity;'; + Blockly.Arduino.variables_['bmePressure'] = 'double bmePressure;'; + Blockly.Arduino.variables_['bmeIAQ'] = 'float bmeIAQ;'; + Blockly.Arduino.variables_['bmeIAQAccuracy'] = 'float bmeIAQAccuracy;'; + Blockly.Arduino.variables_['bmeCO2'] = 'int bmeCO2;'; + Blockly.Arduino.variables_['bmeBreathVocEquivalent'] = 'float bmeBreathVocEquivalent;' + + Blockly.Arduino.functionNames_['checkIaqSensorStatus'] = ` + void checkIaqSensorStatus(void) + { + if (iaqSensor.status != BSEC_OK) { + if (iaqSensor.status < BSEC_OK) { + for (;;) + errLeds(); /* Halt in case of failure */ + } + } + + if (iaqSensor.bme680Status != BME680_OK) { + if (iaqSensor.bme680Status < BME680_OK) { + for (;;) + errLeds(); /* Halt in case of failure */ + } + } + } + `; + Blockly.Arduino.functionNames_['errLeds'] = ` + void errLeds(void) + { + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); + delay(100); + digitalWrite(LED_BUILTIN, LOW); + delay(100); + }`; + //Setup Code + Blockly.Arduino.setupCode_['Wire.begin'] = 'Wire.begin();'; + Blockly.Arduino.setupCode_['iaqSensor.begin'] = 'iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire);'; + Blockly.Arduino.setupCode_['checkIaqSensorStatus'] = 'checkIaqSensorStatus();'; + Blockly.Arduino.setupCode_['bsec_sensorlist'] = ` + bsec_virtual_sensor_t sensorList[10] = { + BSEC_OUTPUT_RAW_TEMPERATURE, + BSEC_OUTPUT_RAW_PRESSURE, + BSEC_OUTPUT_RAW_HUMIDITY, + BSEC_OUTPUT_RAW_GAS, + BSEC_OUTPUT_IAQ, + BSEC_OUTPUT_STATIC_IAQ, + BSEC_OUTPUT_CO2_EQUIVALENT, + BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, + }; + `; + Blockly.Arduino.setupCode_['iaqSensorUpdateSubscription'] = 'iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);\ncheckIaqSensorStatus();'; + //Loop Code + Blockly.Arduino.loopCodeOnce_['iaqloop'] = ` + if (iaqSensor.run()) { + bmeTemperatur = iaqSensor.temperature; + bmeHumidity = iaqSensor.humidity; + bmePressure = iaqSensor.pressure; + bmeIAQ = iaqSensor.iaq; + bmeIAQAccuracy = iaqSensor.iaqAccuracy; + bmeCO2 = iaqSensor.co2Equivalent; + bmeBreathVocEquivalent = iaqSensor.breathVocEquivalent; + } else { + checkIaqSensorStatus(); + } + `; + switch (dropdown_name) { + case 'temperature': + var code = 'bmeTemperatur'; + break; + case 'humidity': + var code = 'bmeHumidity'; + break; + case 'pressure': + var code = 'bmePressure' + break; + case 'IAQ': + var code = 'bmeIAQ'; + break; + case 'IAQAccuracy': + var code = 'bmeIAQAccuracy'; + break; + case 'CO2': + var code = 'bmeCO2'; + break; + case 'breathVocEquivalent': + var code = 'bmeBreathVocEquivalent'; + break; + } + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + + +/** + * Ultrasonic Distance Sensor + * + */ + +Blockly.Arduino.sensebox_sensor_ultrasonic_ranger = function () { + var dropdown_pin_RX = this.getFieldValue('ultrasonic_trigger'); + var dropdown_pin_TX = this.getFieldValue('ultrasonic_echo'); + var port = this.getFieldValue('port'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['var_ultrasonic' + port] = 'Ultrasonic Ultrasonic' + port + '(' + dropdown_pin_RX + ',' + dropdown_pin_TX + ');'; + var code; + code = 'Ultrasonic' + port + '.getDistance()'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * Microphone + * + */ + +Blockly.Arduino.sensebox_sensor_sound = function () { + var dropdown_pin = this.getFieldValue('PIN'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['define_microphone'] = 'Microphone microphone(' + dropdown_pin + ');' + var code = 'microphone.getValue()'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; diff --git a/src/components/Blockly/generator/sensebox-telegram.js b/src/components/Blockly/generator/sensebox-telegram.js new file mode 100644 index 0000000..6037b2b --- /dev/null +++ b/src/components/Blockly/generator/sensebox-telegram.js @@ -0,0 +1,58 @@ +import * as Blockly from 'blockly/core'; +import { Block } from 'blockly'; + + +/** + * Telegram Bot by re:edu + */ +Blockly.Arduino.sensebox_telegram = function (Block) { + let token = Block.getFieldValue('telegram_token'); + Blockly['Arduino'].libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly['Arduino'].libraries_['library_telegram'] = `#include ` + Blockly['Arduino'].functionNames_['WiFiSSLClient'] = 'WiFiSSLClient client;'; + Blockly['Arduino'].functionNames_['telegram_objects'] = `#define BOTtoken "${token}" // your Bot Token (Get from Botfather) + + UniversalTelegramBot bot(BOTtoken, client);` + + let code = 'testcode'; + return code; +}; + +Blockly.Arduino.sensebox_telegram_do = function (block) { + var messageProcessing = Blockly.Arduino.statementToCode(block, 'telegram_do', Blockly.Arduino.ORDER_ATOMIC); + + Blockly.Arduino.definitions_['telegram_variables'] = `int Bot_mtbs = 1000; //mean time between scan messages + long Bot_lasttime; //last time messages' scan has been done` + + Blockly.Arduino.loopCodeOnce_['sensebox_telegram_loop'] = `if (millis() > Bot_lasttime + Bot_mtbs) { + int numNewMessages = bot.getUpdates(bot.last_message_received + 1); + while(numNewMessages) { + for(int i=0; i` - Blockly['Arduino'].functionNames_['WiFiSSLClient'] = 'WiFiSSLClient client;'; - Blockly['Arduino'].functionNames_['telegram_objects'] = `#define BOTtoken "${token}" // your Bot Token (Get from Botfather) - - UniversalTelegramBot bot(BOTtoken, client);` - - let code = 'testcode'; - return code; -}; \ No newline at end of file diff --git a/src/components/Blockly/generator/time.js b/src/components/Blockly/generator/time.js new file mode 100644 index 0000000..57fc5ec --- /dev/null +++ b/src/components/Blockly/generator/time.js @@ -0,0 +1,80 @@ +import Blockly from 'blockly'; + +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Arduino code generator for the Time blocks. + * Arduino built-in function docs: http://arduino.cc/en/Reference/HomePage + */ + +/** + * Code generator for the delay Arduino block. + * Arduino code: loop { delay(X); } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['time_delay'] = function (block) { + var delayTime = Blockly.Arduino.valueToCode( + block, 'DELAY_TIME_MILI', Blockly.Arduino.ORDER_ATOMIC) || '0'; + var code = 'delay(' + delayTime + ');\n'; + return code; +}; + +/** + * Code generator for the delayMicroseconds block. + * Arduino code: loop { delayMicroseconds(X); } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['time_delaymicros'] = function (block) { + var delayTimeMs = Blockly.Arduino.valueToCode( + block, 'DELAY_TIME_MICRO', Blockly.Arduino.ORDER_ATOMIC) || '0'; + var code = 'delayMicroseconds(' + delayTimeMs + ');\n'; + return code; +}; + +/** + * Code generator for the elapsed time in milliseconds block. + * Arduino code: loop { millis() } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['time_millis'] = function (block) { + var code = 'millis()'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * Code generator for the elapsed time in microseconds block. + * Arduino code: loop { micros() } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['time_micros'] = function (block) { + var code = 'micros()'; + return [code, Blockly.Arduino.ORDER_ATOMIC]; +}; + +/** + * Code generator for the wait forever (end of program) block + * Arduino code: loop { while(true); } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {string} Completed code. + */ +Blockly.Arduino['infinite_loop'] = function (block) { + return 'while(true);\n'; +}; + +Blockly.Arduino.sensebox_interval_timer = function (block) { + var interval = this.getFieldValue('interval'); + Blockly.Arduino.variables_['define_interval_variables'] = 'const long interval = ' + interval + ';\nlong time_start = 0;\nlong time_actual = 0;'; + var branch = Blockly.Arduino.statementToCode(block, 'DO'); + var code = 'time_start = millis();\n'; + code += 'if (time_start > time_actual + interval) {\n time_actual = millis();\n' + code += branch; + code += '}\n' + return code; +}; \ No newline at end of file diff --git a/src/components/Blockly/helpers/colour.js b/src/components/Blockly/helpers/colour.js new file mode 100644 index 0000000..d2f5c27 --- /dev/null +++ b/src/components/Blockly/helpers/colour.js @@ -0,0 +1,16 @@ + +const colours = { + sensebox: 120, + logic: 210, + loops: 10, + math: 230, + io: 60, + procedures: 290, + time: 140, +} + + +export const getColour = () => { + return colours; +}; + diff --git a/src/components/Blockly/helpers/types.js b/src/components/Blockly/helpers/types.js new file mode 100644 index 0000000..72feab0 --- /dev/null +++ b/src/components/Blockly/helpers/types.js @@ -0,0 +1,221 @@ +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Blockly Types declarations and helper functions to identify + * types. + */ + + +/** Single character. */ +export const CHARACTER = { + typeId: 'Character', + typeMsgName: 'ARD_TYPE_CHAR', + compatibleTypes: [] +} + +export const BOOLEAN = { + typeId: 'Boolean', + typeMsgName: 'ARD_TYPE_BOOL', + compatibleTypes: ['Boolean'] +} + +/** Text string. */ +export const TEXT = { + typeId: 'Text', + typeMsgName: 'ARD_TYPE_TEXT', + compatibleTypes: [] +} + +/** Short integer number. */ +export const SHORT_NUMBER = { + typeId: 'Short Number', + typeMsgName: 'ARD_TYPE_SHORT', + compatibleTypes: [] // Circular dependencies, add after all declarations +} + +/** Integer number. */ +export const NUMBER = { + typeId: 'Number', + typeMsgName: 'ARD_TYPE_NUMBER', + compatibleTypes: ['Number'] // Circular dependencies, add after all declarations +} + +/** Large integer number. */ +export const LARGE_NUMBER = { + typeId: 'Large Number', + typeMsgName: 'ARD_TYPE_LONG', + compatibleTypes: [] // Circular dependencies, add after all declarations +} + +/** Decimal/floating point number. */ +export const DECIMAL = { + typeId: 'Decimal', + typeMsgName: 'ARD_TYPE_DECIMAL', + compatibleTypes: [BOOLEAN.typeId, + NUMBER, + SHORT_NUMBER, + LARGE_NUMBER] +} + +/** Array/List of items. */ +export const ARRAY = { + typeId: 'Array', + typeMsgName: 'ARD_TYPE_ARRAY', + compatibleTypes: [] +} + +/** Null indicate there is no type. */ +export const NULL = { + typeId: 'Null', + typeMsgName: 'ARD_TYPE_NULL', + compatibleTypes: [] +} + +/** Type not defined, or not yet defined. */ +export const UNDEF = { + typeId: 'Undefined', + typeMsgName: 'ARD_TYPE_UNDEF', + compatibleTypes: [] +} + +/** Set when no child block (meant to define the variable type) is connected. */ +export const CHILD_BLOCK_MISSING = { + typeId: 'ChildBlockMissing', + typeMsgName: 'ARD_TYPE_CHILDBLOCKMISSING', + compatibleTypes: [] +} + +// /** +// * Some Types have circular dependencies on their compatibilities, so add them +// * after declaration. +// */ +// Blockly.Types.NUMBER.addCompatibleTypes([ +// Blockly.Types.BOOLEAN, +// Blockly.Types.SHORT_NUMBER, +// Blockly.Types.LARGE_NUMBER, +// Blockly.Types.DECIMAL]); + +// Blockly.Types.SHORT_NUMBER.addCompatibleTypes([ +// Blockly.Types.BOOLEAN, +// Blockly.Types.NUMBER, +// Blockly.Types.LARGE_NUMBER, +// Blockly.Types.DECIMAL]); + +// Blockly.Types.LARGE_NUMBER.addCompatibleTypes([ +// Blockly.Types.BOOLEAN, +// Blockly.Types.SHORT_NUMBER, +// Blockly.Types.NUMBER, +// Blockly.Types.DECIMAL]); + +// /** +// * Adds another type to the Blockly.Types collection. +// * @param {string} typeId_ Identifiable name of the type. +// * @param {string} typeMsgName_ Name of the member variable from Blockly.Msg +// * object to identify the translateble string.for the Type name. +// * @param {Array} compatibleTypes_ List of types this Type is +// * compatible with. +// */ +// Blockly.Types.addType = function (typeId_, typeMsgName_, compatibleTypes_) { +// // The Id is used as the key from the value pair in the BlocklyTypes object +// var key = typeId_.toUpperCase().replace(/ /g, '_'); +// if (Blockly.Types[key] !== undefined) { +// throw 'The Blockly type ' + key + ' already exists.'; +// } +// Blockly.Types[key] = new Blockly.Type({ +// typeId: typeId_, +// typeName: typeMsgName_, +// compatibleTypes: compatibleTypes_ +// }); +// }; + +// /** +// * Converts the static types dictionary in to a an array with 2-item arrays. +// * This array only contains the valid types, excluding any error or temp types. +// * @return {!Array>} Blockly types in the format described above. +// */ +// Blockly.Types.getValidTypeArray = function () { +// var typesArray = []; +// for (var typeKey in Blockly.Types) { +// if ((typeKey !== 'UNDEF') && (typeKey !== 'CHILD_BLOCK_MISSING') && +// (typeKey !== 'NULL') && (typeKey !== 'ARRAY') && +// (typeof Blockly.Types[typeKey] !== 'function') && +// !(Blockly.Types[typeKey] instanceof RegExp)) { +// typesArray.push([Blockly.Types[typeKey].typeName, typeKey]); +// } +// } +// return typesArray; +// }; + +// /** +// * Navigates through child blocks of the argument block to get this block type. +// * @param {!Blockly.Block} block Block to navigate through children. +// * @return {Blockly.Type} Type of the input block. +// */ +// Blockly.Types.getChildBlockType = function (block) { +// var blockType = null; +// var nextBlock = block; +// // Only checks first input block, so it decides the type. Incoherences amongst +// // multiple inputs dealt at a per-block level with their own block warnings +// while (nextBlock && (nextBlock.getBlockType === undefined) && +// (nextBlock.inputList.length > 0) && +// (nextBlock.inputList[0].connection)) { +// nextBlock = nextBlock.inputList[0].connection.targetBlock(); +// } +// if (nextBlock === block) { +// // Set variable block is empty, so no type yet +// blockType = Blockly.Types.CHILD_BLOCK_MISSING; +// } else if (nextBlock === null) { +// // Null return from targetBlock indicates no block connected +// blockType = Blockly.Types.CHILD_BLOCK_MISSING; +// } else { +// var func = nextBlock.getBlockType; +// if (func) { +// blockType = nextBlock.getBlockType(); +// } else { +// // Most inner block, supposed to define a type, is missing getBlockType() +// blockType = Blockly.Types.NULL; +// } +// } +// return blockType; +// }; + +// /** +// * Regular expressions to identify an integer. +// * @private +// */ +// Blockly.Types.regExpInt_ = new RegExp(/^-?\d+$/); + +// /** +// * Regular expressions to identify a decimal. +// * @private +// */ +// Blockly.Types.regExpFloat_ = new RegExp(/^-?[0-9]*[.][0-9]+$/); + +// /** +// * Uses regular expressions to identify if the input number is an integer or a +// * floating point. +// * @param {string} numberString String of the number to identify. +// * @return {!Blockly.Type} Blockly type. +// */ +// Blockly.Types.identifyNumber = function (numberString) { +// if (Blockly.Types.regExpInt_.test(numberString)) { +// var intValue = parseInt(numberString); +// if (isNaN(intValue)) { +// return Blockly.Types.NULL; +// } +// if (intValue > 32767 || intValue < -32768) { +// return Blockly.Types.LARGE_NUMBER; +// } +// return Blockly.Types.NUMBER; +// } else if (Blockly.Types.regExpFloat_.test(numberString)) { +// return Blockly.Types.DECIMAL; +// } +// return Blockly.Types.NULL; +// }; + + + + diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js index ccbf34d..c0a1ea3 100644 --- a/src/components/Blockly/toolbox/Toolbox.js +++ b/src/components/Blockly/toolbox/Toolbox.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import BlocklyComponent, { Block, Value, Field, Shadow, Category } from '../'; +import { getColour } from '../helpers/colour' class Toolbox extends React.Component { @@ -10,23 +11,36 @@ class Toolbox extends React.Component { render() { return ( - - + + + + + + + + + - + + + + + + + - - + + - + @@ -54,7 +68,27 @@ class Toolbox extends React.Component { - + + + + + 1000 + + + + + + + 100 + + + + + + + + + @@ -98,9 +132,31 @@ class Toolbox extends React.Component { {/* */} - + + + + + + + + + + + + + + + + + 100 + + + + + + ); diff --git a/src/components/Home.js b/src/components/Home.js index 7aed6c4..3038ba0 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -11,6 +11,7 @@ import Grid from '@material-ui/core/Grid'; import FormControlLabel from '@material-ui/core/FormControlLabel'; import Switch from '@material-ui/core/Switch'; + class Home extends Component { state = { From 4e2b25947d201870f63b577baf6d34af2b237a0c Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 11:27:53 +0200 Subject: [PATCH 03/12] solve compiling warnings --- src/components/Blockly/BlocklyWindow.js | 4 +- src/components/Blockly/blocks/io.js | 1 - src/components/Blockly/blocks/logic.js | 1 - src/components/Blockly/blocks/math.js | 2 - .../Blockly/blocks/sensebox-osem.js | 10 ++--- .../Blockly/blocks/sensebox-sensors.js | 16 ++++---- src/components/Blockly/blocks/sensebox.js | 2 +- src/components/Blockly/generator/generator.js | 1 - src/components/Blockly/generator/io.js | 1 - src/components/Blockly/generator/logic.js | 1 - src/components/Blockly/generator/loops.js | 4 +- src/components/Blockly/generator/math.js | 21 +++++----- .../Blockly/generator/procedures.js | 4 +- .../Blockly/generator/sensebox-osem.js | 12 +++--- .../Blockly/generator/sensebox-sensors.js | 31 ++++++++------- .../Blockly/generator/sensebox-telegram.js | 39 +++++++++---------- src/components/Blockly/helpers/board.js | 2 +- src/components/Blockly/toolbox/Toolbox.js | 7 +--- 18 files changed, 76 insertions(+), 83 deletions(-) diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js index f507bad..7e06566 100644 --- a/src/components/Blockly/BlocklyWindow.js +++ b/src/components/Blockly/BlocklyWindow.js @@ -3,10 +3,8 @@ import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { onChangeWorkspace } from '../../actions/workspaceActions'; -import BlocklyComponent, { Block, Value, Field, Shadow, Category } from './'; +import BlocklyComponent from './'; import * as Blockly from 'blockly/core'; -//import * as De from './msg/de'; // de locale files -import * as En from './msg/en'; // en locale files import './blocks/index'; import './generator/index'; diff --git a/src/components/Blockly/blocks/io.js b/src/components/Blockly/blocks/io.js index 104b3f4..0e231e9 100644 --- a/src/components/Blockly/blocks/io.js +++ b/src/components/Blockly/blocks/io.js @@ -10,7 +10,6 @@ * * TODO: maybe change this to a "PIN" BlocklyType */ -import { defineBlocksWithJsonArray } from 'blockly'; import Blockly from 'blockly/core'; import { selectedBoard } from '../helpers/board' import * as Types from '../helpers/types' diff --git a/src/components/Blockly/blocks/logic.js b/src/components/Blockly/blocks/logic.js index 0ba9179..6b17ee4 100644 --- a/src/components/Blockly/blocks/logic.js +++ b/src/components/Blockly/blocks/logic.js @@ -1,4 +1,3 @@ -import { defineBlocksWithJsonArray } from 'blockly'; import Blockly from 'blockly/core'; diff --git a/src/components/Blockly/blocks/math.js b/src/components/Blockly/blocks/math.js index 49bdf7d..e69de29 100644 --- a/src/components/Blockly/blocks/math.js +++ b/src/components/Blockly/blocks/math.js @@ -1,2 +0,0 @@ - -import Blockly from 'blockly'; \ No newline at end of file diff --git a/src/components/Blockly/blocks/sensebox-osem.js b/src/components/Blockly/blocks/sensebox-osem.js index a6f4eaf..f6b8b66 100644 --- a/src/components/Blockly/blocks/sensebox-osem.js +++ b/src/components/Blockly/blocks/sensebox-osem.js @@ -1,6 +1,5 @@ import * as Blockly from 'blockly/core'; import { getColour } from '../helpers/colour'; -import Block from 'blockly' Blockly.Blocks['sensebox_osem_connection'] = { @@ -28,8 +27,7 @@ Blockly.Blocks['sensebox_osem_connection'] = { this.setNextStatement(true, null); }, onchange: function (e) { - var block = this; - var blocks = block.getDescendants() + //Blockly.Blocks.sensebox.getDescendants = blocks; }, @@ -54,7 +52,7 @@ Blockly.Blocks['sensebox_osem_connection'] = { updateShape_: function () { var extraFieldExist = this.getFieldValue('gps'); var input = this.getFieldValue('type'); - if ((input == 'Mobile') && extraFieldExist == null) { + if ((input === 'Mobile') && extraFieldExist === null) { this.appendValueInput('lat', 'Number') .appendField(Blockly.Msg.senseBox_gps_lat, 'gps'); this.appendValueInput('lng', 'Number') @@ -65,7 +63,7 @@ Blockly.Blocks['sensebox_osem_connection'] = { .appendField(Blockly.Msg.senseBox_gps_timeStamp); } - if (input == 'Stationary' && extraFieldExist != null) { + if (input === 'Stationary' && extraFieldExist !== null) { this.removeInput('lat'); this.removeInput('lng'); this.removeInput('altitude'); @@ -98,7 +96,7 @@ Blockly.Blocks['sensebox_send_to_osem'] = { // Is the block nested in a loop? var block = this; do { - if (this.LOOP_TYPES.indexOf(block.type) != -1) { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { legal = true; break; } diff --git a/src/components/Blockly/blocks/sensebox-sensors.js b/src/components/Blockly/blocks/sensebox-sensors.js index 8c1c24b..0308d7e 100644 --- a/src/components/Blockly/blocks/sensebox-sensors.js +++ b/src/components/Blockly/blocks/sensebox-sensors.js @@ -111,7 +111,7 @@ Blockly.Blocks['sensebox_sensor_pressure'] = { init: function () { var dropdownOptions = [[Blockly.Msg.senseBox_pressure, "Pressure"], [Blockly.Msg.senseBox_temp, "Temperature"], [Blockly.Msg.senseBox_gps_alt, "Altitude"]]; var dropdown = new Blockly.FieldDropdown(dropdownOptions, function (option) { - var input = (option == 'Pressure') || (option == 'Temperature') || (option == 'Altitude'); + var input = (option === 'Pressure') || (option === 'Temperature') || (option === 'Altitude'); this.sourceBlock_.updateShape_(input); }); this.appendDummyInput() @@ -132,7 +132,7 @@ Blockly.Blocks['sensebox_sensor_pressure'] = { */ domToMutation: function (xmlElement) { - var input = (xmlElement.getAttribute('port')); + (xmlElement.getAttribute('port')); }, /** @@ -156,7 +156,7 @@ Blockly.Blocks['sensebox_sensor_pressure'] = { updateShape_: function () { var extraFieldExist = this.getFieldValue('referencePressure'); var input = this.getFieldValue('NAME'); - if (input == 'Altitude' && extraFieldExist == null) { + if (input === 'Altitude' && extraFieldExist === null) { this.appendDummyInput('extraField') .setAlign(Blockly.ALIGN_RIGHT) .appendField(Blockly.Msg.senseBox_pressure_referencePressure) @@ -164,13 +164,13 @@ Blockly.Blocks['sensebox_sensor_pressure'] = { .appendField(Blockly.Msg.senseBox_pressure_referencePressure_dim); } - if ((input == 'Pressure' || input == 'Temperature') && extraFieldExist != null) { + if ((input === 'Pressure' || input === 'Temperature') && extraFieldExist !== null) { this.removeInput('extraField'); } }, getBlockType: function () { var input = this.getFieldValue('NAME'); - if (input == 'Temperature') { + if (input === 'Temperature') { return Types.DECIMAL.typeId; } else { return Types.LARGE_NUMBER.typeId; @@ -215,7 +215,7 @@ Blockly.Blocks['sensebox_sensor_ultrasonic_ranger'] = { var dropdownOptions = [[Blockly.Msg.senseBox_ultrasonic_port_A, 'A'], [Blockly.Msg.senseBox_ultrasonic_port_B, 'B'], [Blockly.Msg.senseBox_ultrasonic_port_C, 'C']]; var dropdown = new Blockly.FieldDropdown(dropdownOptions, function (option) { - var input = (option == 'A') || (option == 'B') || (option == 'C'); + var input = (option === 'A') || (option === 'B') || (option === 'C'); this.sourceBlock_.updateShape_(input); }); @@ -241,7 +241,7 @@ Blockly.Blocks['sensebox_sensor_ultrasonic_ranger'] = { * @this Blockly.Block */ domToMutation: function (xmlElement) { - var input = (xmlElement.getAttribute('port')); + (xmlElement.getAttribute('port')); }, /** @@ -277,6 +277,8 @@ Blockly.Blocks['sensebox_sensor_ultrasonic_ranger'] = { this.setFieldValue('5', 'ultrasonic_trigger'); this.setFieldValue('6', 'ultrasonic_echo'); break; + default: + break; } }, diff --git a/src/components/Blockly/blocks/sensebox.js b/src/components/Blockly/blocks/sensebox.js index 43ebcbb..fd40910 100644 --- a/src/components/Blockly/blocks/sensebox.js +++ b/src/components/Blockly/blocks/sensebox.js @@ -1,4 +1,4 @@ -import Blockly from 'blockly'; + diff --git a/src/components/Blockly/generator/generator.js b/src/components/Blockly/generator/generator.js index 89cd398..8b5808b 100644 --- a/src/components/Blockly/generator/generator.js +++ b/src/components/Blockly/generator/generator.js @@ -25,7 +25,6 @@ // https://developers.google.com/blockly/guides/create-custom-blocks/generating-code import * as Blockly from 'blockly/core'; -import * as _ from 'lodash'; /** * Arduino code generator. diff --git a/src/components/Blockly/generator/io.js b/src/components/Blockly/generator/io.js index 19cc7b2..991e4e8 100644 --- a/src/components/Blockly/generator/io.js +++ b/src/components/Blockly/generator/io.js @@ -1,5 +1,4 @@ import * as Blockly from 'blockly/core'; -import { Block } from 'blockly'; /** * Function for 'set pin' (X) to a state (Y). diff --git a/src/components/Blockly/generator/logic.js b/src/components/Blockly/generator/logic.js index 402a020..443b7b2 100644 --- a/src/components/Blockly/generator/logic.js +++ b/src/components/Blockly/generator/logic.js @@ -1,5 +1,4 @@ import * as Blockly from 'blockly/core'; -import { Block } from 'blockly'; Blockly.Arduino['logic_boolean'] = function (Block) { // Boolean values true and false. diff --git a/src/components/Blockly/generator/loops.js b/src/components/Blockly/generator/loops.js index cfabf36..e9804bf 100644 --- a/src/components/Blockly/generator/loops.js +++ b/src/components/Blockly/generator/loops.js @@ -1,5 +1,5 @@ import * as Blockly from 'blockly/core'; -import { Block } from 'blockly'; + Blockly['Arduino']['controls_repeat_ext'] = function (Block) { // Repeat n times. @@ -111,6 +111,8 @@ Blockly['Arduino']['controls_flow_statements'] = function (Block) { return 'break;\n'; case 'CONTINUE': return 'continue;\n'; + default: + break; } throw Error('Unknown flow statement.'); }; \ No newline at end of file diff --git a/src/components/Blockly/generator/math.js b/src/components/Blockly/generator/math.js index 0832e0c..efb02e1 100644 --- a/src/components/Blockly/generator/math.js +++ b/src/components/Blockly/generator/math.js @@ -1,6 +1,5 @@ import * as Blockly from 'blockly/core'; -import { Block } from 'blockly'; /** * @license Licensed under the Apache License, Version 2.0 (the "License"): @@ -23,9 +22,9 @@ import { Block } from 'blockly'; Blockly.Arduino['math_number'] = function (block) { // Numeric value. var code = parseFloat(block.getFieldValue('NUM')); - if (code == Infinity) { + if (code === Infinity) { code = 'INFINITY'; - } else if (code == -Infinity) { + } else if (code === -Infinity) { code = '-INFINITY'; } return [code, Blockly.Arduino.ORDER_ATOMIC]; @@ -71,21 +70,21 @@ Blockly.Arduino['math_single'] = function (block) { var operator = block.getFieldValue('OP'); var code; var arg; - if (operator == 'NEG') { + if (operator === 'NEG') { // Negation is a special case given its different operator precedents. arg = Blockly.Arduino.valueToCode(block, 'NUM', Blockly.Arduino.ORDER_UNARY_PREFIX) || '0'; - if (arg[0] == '-') { + if (arg[0] === '-') { // --3 is not legal in C++ in this context. arg = ' ' + arg; } code = '-' + arg; return [code, Blockly.Arduino.ORDER_UNARY_PREFIX]; } - if (operator == 'ABS' || operator.substring(0, 5) == 'ROUND') { + if (operator === 'ABS' || operator.substring(0, 5) === 'ROUND') { arg = Blockly.Arduino.valueToCode(block, 'NUM', Blockly.Arduino.ORDER_UNARY_POSTFIX) || '0'; - } else if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { + } else if (operator === 'SIN' || operator === 'COS' || operator === 'TAN') { arg = Blockly.Arduino.valueToCode(block, 'NUM', Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; } else { @@ -127,6 +126,8 @@ Blockly.Arduino['math_single'] = function (block) { case 'TAN': code = 'tan(' + arg + ' / 180 * Math.PI)'; break; + default: + break; } if (code) { return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX]; @@ -146,7 +147,7 @@ Blockly.Arduino['math_single'] = function (block) { code = 'atan(' + arg + ') / M_PI * 180'; break; default: - throw 'Unknown math operator: ' + operator; + throw new Error('Unknown math operator: ' + operator); } return [code, Blockly.Arduino.ORDER_MULTIPLICATIVE]; }; @@ -184,7 +185,7 @@ Blockly.Arduino['math_number_property'] = function (block) { Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; var dropdown_property = block.getFieldValue('PROPERTY'); var code; - if (dropdown_property == 'PRIME') { + if (dropdown_property === 'PRIME') { var func = [ 'boolean ' + Blockly.Arduino.DEF_FUNC_NAME + '(int n) {', ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods', @@ -232,6 +233,8 @@ Blockly.Arduino['math_number_property'] = function (block) { Blockly.Arduino.ORDER_MULTIPLICATIVE) || '0'; code = number_to_check + ' % ' + divisor + ' == 0'; break; + default: + break; } return [code, Blockly.Arduino.ORDER_EQUALITY]; }; diff --git a/src/components/Blockly/generator/procedures.js b/src/components/Blockly/generator/procedures.js index 92e57a7..59a4ec8 100644 --- a/src/components/Blockly/generator/procedures.js +++ b/src/components/Blockly/generator/procedures.js @@ -1,5 +1,5 @@ import * as Blockly from 'blockly/core'; -import { Block } from 'blockly'; + /** * Code generator to add code into the setup() and loop() functions. @@ -13,7 +13,7 @@ Blockly.Arduino['arduino_functions'] = function (block) { var targetBlock = block.getInputTargetBlock(name); var code = Blockly.Arduino.blockToCode(targetBlock); if (typeof code != 'string') { - throw 'Expecting code from statement block "' + targetBlock.type + '".'; + throw new Error('Expecting code from statement block "' + targetBlock.type + '".'); } return code; } diff --git a/src/components/Blockly/generator/sensebox-osem.js b/src/components/Blockly/generator/sensebox-osem.js index ee19a76..d4058ce 100644 --- a/src/components/Blockly/generator/sensebox-osem.js +++ b/src/components/Blockly/generator/sensebox-osem.js @@ -1,6 +1,4 @@ -import Blockly, { Blocks } from 'blockly'; -import { getColour } from '../helpers/colour' -import Block from 'blockly'; +import Blockly from 'blockly'; /** @@ -20,7 +18,7 @@ Blockly.Arduino.sensebox_osem_connection = function (Block) { var box_id = this.getFieldValue('BoxID'); var host = this.getFieldValue('host'); var branch = Blockly.Arduino.statementToCode(Block, 'DO'); - var blocks = Blockly.Block.getDescendants; + //var blocks = Blockly.Block.getDescendants; var type = this.getFieldValue('type'); var ssl = this.getFieldValue('SSL'); var port = 0; @@ -36,10 +34,10 @@ Blockly.Arduino.sensebox_osem_connection = function (Block) { Blockly.Arduino.definitions_['num_sensors'] = 'static const uint8_t NUM_SENSORS = ' + num_sensors + ';' Blockly.Arduino.definitions_['SenseBoxID'] = 'const char SENSEBOX_ID [] PROGMEM = "' + box_id + '";'; Blockly.Arduino.definitions_['host'] = 'const char server [] PROGMEM =' + host + ';'; - if (ssl == 'TRUE') { + if (ssl === 'TRUE') { Blockly.Arduino.definitions_['WiFiSSLClient'] = 'WiFiSSLClient client;'; port = 443; - } else if (ssl == 'FALSE') { + } else if (ssl === 'FALSE') { Blockly.Arduino.definitions_['WiFiClient'] = 'WiFiClient client;'; port = 80; } @@ -170,7 +168,7 @@ Blockly.Arduino.sensebox_osem_connection = function (Block) { } } }` - var code = ''; + code = ''; code += branch; code += 'submitValues(' + lat + ',' + lng + ',' + altitude + ',' + timestamp + ');\n'; } diff --git a/src/components/Blockly/generator/sensebox-sensors.js b/src/components/Blockly/generator/sensebox-sensors.js index e413075..655ecc6 100644 --- a/src/components/Blockly/generator/sensebox-sensors.js +++ b/src/components/Blockly/generator/sensebox-sensors.js @@ -1,6 +1,4 @@ import Blockly from 'blockly'; -import { getColour } from '../helpers/colour'; -import { selectedBoard } from '../helpers/board'; /** * HDC1080 Temperature and Humidity Sensor @@ -23,16 +21,17 @@ Blockly.Arduino.sensebox_sensor_temp_hum = function () { Blockly.Arduino.sensebox_sensor_uv_light = function () { var dropdown_name = this.getFieldValue('NAME'); + let code = ''; Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; if (dropdown_name === 'UvIntensity') { Blockly.Arduino.definitions_['define_veml'] = 'VEML6070 veml;' Blockly.Arduino.setupCode_['sensebox_sensor_uv_light'] = 'veml.begin();' - var code = 'veml.get' + dropdown_name + '()'; + code = 'veml.get' + dropdown_name + '()'; } if (dropdown_name === 'Illuminance') { Blockly.Arduino.definitions_['define_tsl'] = 'TSL45315 tsl;' Blockly.Arduino.setupCode_['sensebox_sensor_illuminance'] = 'tsl.begin();' - var code = 'tsl.get' + dropdown_name + '()'; + code = 'tsl.get' + dropdown_name + '()'; } return [code, Blockly.Arduino.ORDER_ATOMIC]; }; @@ -76,15 +75,16 @@ Blockly.Arduino.sensebox_sensor_sds011 = function () { Blockly.Arduino.sensebox_sensor_pressure = function () { var dropdown_name = this.getFieldValue('NAME'); + var code = ''; var referencePressure = this.getFieldValue('referencePressure'); Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; Blockly.Arduino.definitions_['define_pressure'] = 'BMP280 bmp_sensor;'; Blockly.Arduino.setupCode_['sensebox_bmp_sensor'] = 'bmp_sensor.begin();'; - if (dropdown_name === 'Pressure' || dropdown_name == 'Temperature') { - var code = 'bmp_sensor.get' + dropdown_name + '()'; + if (dropdown_name === 'Pressure' || dropdown_name === 'Temperature') { + code = 'bmp_sensor.get' + dropdown_name + '()'; } else if (dropdown_name === 'Altitude') { - var code = 'bmp_sensor.getAltitude(' + referencePressure + ')'; + code = 'bmp_sensor.getAltitude(' + referencePressure + ')'; } return [code, Blockly.Arduino.ORDER_ATOMIC]; }; @@ -98,6 +98,7 @@ Blockly.Arduino.sensebox_sensor_pressure = function () { Blockly.Arduino.sensebox_sensor_bme680_bsec = function () { var dropdown_name = this.getFieldValue('dropdown'); + let code = ''; Blockly.Arduino.libraries_['library_bsec'] = '#include "bsec.h"'; Blockly.Arduino.definitions_['bsec_iaqSensor'] = 'Bsec iaqSensor;' Blockly.Arduino.variables_['bmeTemperatur'] = 'float bmeTemperatur;'; @@ -170,25 +171,27 @@ Blockly.Arduino.sensebox_sensor_bme680_bsec = function () { `; switch (dropdown_name) { case 'temperature': - var code = 'bmeTemperatur'; + code = 'bmeTemperatur'; break; case 'humidity': - var code = 'bmeHumidity'; + code = 'bmeHumidity'; break; case 'pressure': - var code = 'bmePressure' + code = 'bmePressure' break; case 'IAQ': - var code = 'bmeIAQ'; + code = 'bmeIAQ'; break; case 'IAQAccuracy': - var code = 'bmeIAQAccuracy'; + code = 'bmeIAQAccuracy'; break; case 'CO2': - var code = 'bmeCO2'; + code = 'bmeCO2'; break; case 'breathVocEquivalent': - var code = 'bmeBreathVocEquivalent'; + code = 'bmeBreathVocEquivalent'; + break; + default: break; } return [code, Blockly.Arduino.ORDER_ATOMIC]; diff --git a/src/components/Blockly/generator/sensebox-telegram.js b/src/components/Blockly/generator/sensebox-telegram.js index 6037b2b..f2b5d72 100644 --- a/src/components/Blockly/generator/sensebox-telegram.js +++ b/src/components/Blockly/generator/sensebox-telegram.js @@ -1,30 +1,29 @@ import * as Blockly from 'blockly/core'; -import { Block } from 'blockly'; /** * Telegram Bot by re:edu */ Blockly.Arduino.sensebox_telegram = function (Block) { - let token = Block.getFieldValue('telegram_token'); - Blockly['Arduino'].libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; - Blockly['Arduino'].libraries_['library_telegram'] = `#include ` - Blockly['Arduino'].functionNames_['WiFiSSLClient'] = 'WiFiSSLClient client;'; - Blockly['Arduino'].functionNames_['telegram_objects'] = `#define BOTtoken "${token}" // your Bot Token (Get from Botfather) + let token = Block.getFieldValue('telegram_token'); + Blockly['Arduino'].libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly['Arduino'].libraries_['library_telegram'] = `#include ` + Blockly['Arduino'].functionNames_['WiFiSSLClient'] = 'WiFiSSLClient client;'; + Blockly['Arduino'].functionNames_['telegram_objects'] = `#define BOTtoken "${token}" // your Bot Token (Get from Botfather) UniversalTelegramBot bot(BOTtoken, client);` - let code = 'testcode'; - return code; + let code = 'testcode'; + return code; }; Blockly.Arduino.sensebox_telegram_do = function (block) { - var messageProcessing = Blockly.Arduino.statementToCode(block, 'telegram_do', Blockly.Arduino.ORDER_ATOMIC); + var messageProcessing = Blockly.Arduino.statementToCode(block, 'telegram_do', Blockly.Arduino.ORDER_ATOMIC); - Blockly.Arduino.definitions_['telegram_variables'] = `int Bot_mtbs = 1000; //mean time between scan messages + Blockly.Arduino.definitions_['telegram_variables'] = `int Bot_mtbs = 1000; //mean time between scan messages long Bot_lasttime; //last time messages' scan has been done` - Blockly.Arduino.loopCodeOnce_['sensebox_telegram_loop'] = `if (millis() > Bot_lasttime + Bot_mtbs) { + Blockly.Arduino.loopCodeOnce_['sensebox_telegram_loop'] = `if (millis() > Bot_lasttime + Bot_mtbs) { int numNewMessages = bot.getUpdates(bot.last_message_received + 1); while(numNewMessages) { for(int i=0; i Date: Fri, 31 Jul 2020 11:36:02 +0200 Subject: [PATCH 04/12] add language key --- src/components/Blockly/BlocklyWindow.js | 3 ++- src/components/Blockly/msg/en.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Blockly/BlocklyWindow.js b/src/components/Blockly/BlocklyWindow.js index 7e06566..228867b 100644 --- a/src/components/Blockly/BlocklyWindow.js +++ b/src/components/Blockly/BlocklyWindow.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { onChangeWorkspace } from '../../actions/workspaceActions'; - +import * as De from './msg/de'; import BlocklyComponent from './'; import * as Blockly from 'blockly/core'; import './blocks/index'; @@ -15,6 +15,7 @@ class BlocklyWindow extends Component { constructor(props) { super(props); this.simpleWorkspace = React.createRef(); + Blockly.setLocale(De); } componentDidMount() { diff --git a/src/components/Blockly/msg/en.js b/src/components/Blockly/msg/en.js index 5f82a77..b4bc8c0 100644 --- a/src/components/Blockly/msg/en.js +++ b/src/components/Blockly/msg/en.js @@ -749,3 +749,4 @@ Blockly.Msg.sensebox_display_show_tip = "Print on Display"; Blockly.Msg.sensebox_sd_filename = "data"; Blockly.Msg.sensebox_soil_smt50 = "Soil Moisture and Temperature (SMT50)"; Blockly.Msg.sensebox_web_readHTML_filename = "File:"; + From 0d70f669359252cd464436f8e3ba1101abf7c983 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 12:31:34 +0200 Subject: [PATCH 05/12] remove devtools --- src/store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store.js b/src/store.js index bd28ae1..bf6460e 100644 --- a/src/store.js +++ b/src/store.js @@ -11,7 +11,7 @@ const store = createStore( initialState, compose( applyMiddleware(...middleware), - window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() + // window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() ) ); From ef80f15782866588a2aae3cbdd351eb8bbb6dc98 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 12:31:47 +0200 Subject: [PATCH 06/12] add display and web blocks --- src/components/Blockly/blocks/index.js | 3 + .../Blockly/blocks/sensebox-display.js | 248 ++++++++++++++++++ src/components/Blockly/blocks/sensebox-web.js | 58 ++++ src/components/Blockly/generator/index.js | 1 + .../Blockly/generator/sensebox-display.js | 90 +++++++ .../Blockly/generator/sensebox-web.js | 25 ++ src/components/Blockly/toolbox/Toolbox.js | 114 ++++++++ 7 files changed, 539 insertions(+) create mode 100644 src/components/Blockly/blocks/sensebox-web.js create mode 100644 src/components/Blockly/generator/sensebox-display.js create mode 100644 src/components/Blockly/generator/sensebox-web.js diff --git a/src/components/Blockly/blocks/index.js b/src/components/Blockly/blocks/index.js index c466260..d1ce014 100644 --- a/src/components/Blockly/blocks/index.js +++ b/src/components/Blockly/blocks/index.js @@ -4,9 +4,12 @@ import './logic'; import './sensebox-sensors'; import './sensebox-telegram'; import './sensebox-osem'; +import './sensebox-web'; +import './sensebox-display'; import './io'; import './math'; import './procedures'; import './time'; + import '../helpers/types' \ No newline at end of file diff --git a/src/components/Blockly/blocks/sensebox-display.js b/src/components/Blockly/blocks/sensebox-display.js index e69de29..2f163b5 100644 --- a/src/components/Blockly/blocks/sensebox-display.js +++ b/src/components/Blockly/blocks/sensebox-display.js @@ -0,0 +1,248 @@ +import * as Blockly from 'blockly/core'; +import { getColour } from '../helpers/colour'; +import * as Types from '../helpers/types' + + +Blockly.Blocks['sensebox_display_beginDisplay'] = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_display_beginDisplay) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setColour(getColour().sensebox); + this.setTooltip(Blockly.Msg.senseBox_display_beginDisplay_tip); + this.setHelpUrl('https://sensebox.de/books'); + } +}; + +Blockly.Blocks['sensebox_display_clearDisplay'] = { + init: function () { + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_display_clearDisplay) + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setColour(getColour().sensebox); + this.setTooltip(Blockly.Msg.senseBox_display_clearDisplay_tip); + this.setHelpUrl('https://sensebox.de/books'); + } +}; + +Blockly.Blocks['sensebox_display_printDisplay'] = { + init: function (block) { + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_display_printDisplay); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_display_color) + .appendField(new Blockly.FieldDropdown([[Blockly.Msg.senseBox_display_white, "WHITE,BLACK"], [Blockly.Msg.senseBox_display_black, "BLACK,WHITE"]]), "COLOR"); + this.appendValueInput("SIZE", 'Number') + .appendField(Blockly.Msg.senseBox_display_setSize); + this.appendValueInput("X", 'Number') + .appendField(Blockly.Msg.senseBox_display_printDisplay_x); + this.appendValueInput("Y", 'Number') + .appendField(Blockly.Msg.senseBox_display_printDisplay_y); + this.appendValueInput('printDisplay') + .appendField(Blockly.Msg.senseBox_display_printDisplay_value) + .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.senseBox_display_printDisplay_tip); + this.setHelpUrl('https://sensebox.de/books'); + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if block is not nested inside a the correct loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + LOOP_TYPES: ['sensebox_display_show'], +}; + + +Blockly.Blocks['sensebox_display_plotDisplay'] = { + init: function () { + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_display_plotDisplay) + this.appendValueInput("Title", 'Text') + .appendField(Blockly.Msg.senseBox_display_plotTitle); + this.appendValueInput("YLabel", 'Text') + .appendField(Blockly.Msg.senseBox_display_plotYLabel); + this.appendValueInput("XLabel", 'Text') + .appendField(Blockly.Msg.senseBox_display_plotXLabel); + this.appendValueInput("XRange1", 'Number') + .appendField(Blockly.Msg.senseBox_display_plotXRange1); + this.appendValueInput("XRange2", 'Number') + .appendField(Blockly.Msg.senseBox_display_plotXRange2) + this.appendValueInput("YRange1", 'Number') + .appendField(Blockly.Msg.senseBox_display_plotYRange1); + this.appendValueInput("YRange2", 'Number') + .appendField(Blockly.Msg.senseBox_display_plotYRange2); + this.setInputsInline(false); + this.appendValueInput("XTick", 'Number') + .appendField(Blockly.Msg.senseBox_display_plotXTick); + this.appendValueInput("YTick", 'Number') + .appendField(Blockly.Msg.senseBox_display_plotYTick); + this.appendValueInput("TimeFrame", 'Number') + .appendField(Blockly.Msg.senseBox_display_plotTimeFrame); + this.appendValueInput('plotDisplay') + .appendField(Blockly.Msg.senseBox_display_printDisplay_value) + .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + this.setTooltip(Blockly.Msg.senseBox_display_printDisplay_tip); + this.setHelpUrl('https://sensebox.de/books'); + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if block is not nested inside a the correct loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + LOOP_TYPES: ['sensebox_display_show'], +}; + +Blockly.Blocks['sensebox_display_show'] = { + init: function () { + + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.sensebox_display_show); + this.appendStatementInput('SHOW'); + this.setTooltip(Blockly.Msg.sensebox_display_show_tip); + this.setHelpUrl(''); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +Blockly.Blocks['sensebox_display_fillCircle'] = { + init: function () { + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.sensebox_display_fillCircle); + this.appendValueInput('X') + .appendField(Blockly.Msg.senseBox_display_printDisplay_x) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('Y') + .appendField(Blockly.Msg.senseBox_display_printDisplay_y) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('Radius') + .appendField(Blockly.Msg.sensebox_display_fillCircle_radius) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendDummyInput('fill') + .appendField(Blockly.Msg.senseBox_display_filled) + .appendField(new Blockly.FieldCheckbox("TRUE"), "FILL"); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if block is not nested inside a the correct loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + LOOP_TYPES: ['sensebox_display_show'], +}; + +Blockly.Blocks['sensebox_display_drawRectangle'] = { + init: function () { + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.sensebox_display_drawRectangle); + this.appendValueInput('X') + .appendField(Blockly.Msg.senseBox_display_printDisplay_x) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('Y') + .appendField(Blockly.Msg.senseBox_display_printDisplay_y) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('width') + .appendField(Blockly.Msg.sensebox_display_drawRectangle_width) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('height') + .appendField(Blockly.Msg.sensebox_display_drawRectangle_height) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendDummyInput('fill') + .appendField(Blockly.Msg.senseBox_display_filled) + .appendField(new Blockly.FieldCheckbox("TRUE"), "FILL"); + this.setInputsInline(false); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if block is not nested inside a the correct loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + LOOP_TYPES: ['sensebox_display_show'], +}; \ No newline at end of file diff --git a/src/components/Blockly/blocks/sensebox-web.js b/src/components/Blockly/blocks/sensebox-web.js new file mode 100644 index 0000000..f82c490 --- /dev/null +++ b/src/components/Blockly/blocks/sensebox-web.js @@ -0,0 +1,58 @@ +import Blockly from 'blockly'; +import { getColour } from '../helpers/colour' + +Blockly.Blocks['sensebox_wifi'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_wifi_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_wifi_connect); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_wifi_ssid) + .appendField(new Blockly.FieldTextInput("SSID"), "SSID"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_output_password) + .appendField(new Blockly.FieldTextInput("Password"), "Password"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + + } + }, + LOOP_TYPES: ['arduino_functions'], +}; + +Blockly.Blocks['sensebox_startap'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_wifi_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField(Blockly.Msg.senseBox_wifi_startap); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_wifi_ssid) + .appendField(new Blockly.FieldTextInput("SSID"), "SSID"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; \ No newline at end of file diff --git a/src/components/Blockly/generator/index.js b/src/components/Blockly/generator/index.js index 263f970..d645206 100644 --- a/src/components/Blockly/generator/index.js +++ b/src/components/Blockly/generator/index.js @@ -3,6 +3,7 @@ import './loops'; import './sensebox-sensors'; import './sensebox-telegram'; import './sensebox-osem'; +import './sensebox-web'; import './logic'; import './math'; import './io'; diff --git a/src/components/Blockly/generator/sensebox-display.js b/src/components/Blockly/generator/sensebox-display.js new file mode 100644 index 0000000..5a83d8d --- /dev/null +++ b/src/components/Blockly/generator/sensebox-display.js @@ -0,0 +1,90 @@ +import * as Blockly from 'blockly/core'; + +/*Display Blocks*/ +Blockly.Arduino.sensebox_display_beginDisplay = function () { + Blockly.Arduino.libraries_['library_spi'] = '#include '; + Blockly.Arduino.libraries_['library_wire'] = '#include '; + Blockly.Arduino.libraries_['library_AdafruitGFX'] = '#include '; + Blockly.Arduino.libraries_['library_AdafruitSSD1306'] = '#include '; + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['define_display'] = '#define OLED_RESET 4\nAdafruit_SSD1306 display(OLED_RESET);'; + Blockly.Arduino.setupCode_['sensebox_display_begin'] = 'senseBoxIO.powerI2C(true);\ndelay(2000);\ndisplay.begin(SSD1306_SWITCHCAPVCC, 0x3D);\ndisplay.display();\ndelay(100);\ndisplay.clearDisplay();'; + var code = ''; + return code; +}; + +Blockly.Arduino.sensebox_display_clearDisplay = function () { + var code = 'display.clearDisplay();\n'; + return code; +}; + +Blockly.Arduino.sensebox_display_printDisplay = function () { + var x = Blockly.Arduino.valueToCode(this, 'X', Blockly.Arduino.ORDER_ATOMIC) || '0' + var y = Blockly.Arduino.valueToCode(this, 'Y', Blockly.Arduino.ORDER_ATOMIC) || '0' + var printDisplay = Blockly.Arduino.valueToCode(this, 'printDisplay', Blockly.Arduino.ORDER_ATOMIC) || '"Keine Eingabe"'; + var size = Blockly.Arduino.valueToCode(this, 'SIZE', Blockly.Arduino.ORDER_ATOMIC) || '1' + var color = this.getFieldValue('COLOR'); + var code = 'display.setCursor(' + x + ',' + y + ');\n'; + code += 'display.setTextSize(' + size + ');\n'; + code += 'display.setTextColor(' + color + ');\n'; + code += 'display.println(' + printDisplay + ');\n'; + return code; +}; + +Blockly.Arduino.sensebox_display_show = function (block) { + var show = Blockly.Arduino.statementToCode(block, 'SHOW'); + var code = ''; + code += show; + code += 'display.display();\n'; + return code; +}; +Blockly.Arduino.sensebox_display_plotDisplay = function () { + var YLabel = Blockly.Arduino.valueToCode(this, 'YLabel', Blockly.Arduino.ORDER_ATOMIC) || 'Y' + var XLabel = Blockly.Arduino.valueToCode(this, 'XLabel', Blockly.Arduino.ORDER_ATOMIC) || 'X' + var Title = Blockly.Arduino.valueToCode(this, 'Title', Blockly.Arduino.ORDER_ATOMIC) || 'Title' + var XRange1 = Blockly.Arduino.valueToCode(this, 'XRange1', Blockly.Arduino.ORDER_ATOMIC) || '0' + var XRange2 = Blockly.Arduino.valueToCode(this, 'XRange2', Blockly.Arduino.ORDER_ATOMIC) || '0' + var YRange1 = Blockly.Arduino.valueToCode(this, 'YRange1', Blockly.Arduino.ORDER_ATOMIC) || '0' + var YRange2 = Blockly.Arduino.valueToCode(this, 'YRange2', Blockly.Arduino.ORDER_ATOMIC) || '0' + var XTick = Blockly.Arduino.valueToCode(this, 'XTick', Blockly.Arduino.ORDER_ATOMIC) || '0' + var YTick = Blockly.Arduino.valueToCode(this, 'YTick', Blockly.Arduino.ORDER_ATOMIC) || '0' + var TimeFrame = Blockly.Arduino.valueToCode(this, 'TimeFrame', Blockly.Arduino.ORDER_ATOMIC) || '0' + var plotDisplay = Blockly.Arduino.valueToCode(this, 'plotDisplay', Blockly.Arduino.ORDER_ATOMIC) || '"Keine Eingabe"'; + Blockly.Arduino.libraries_['library_plot'] = '#include '; + Blockly.Arduino.definitions_['define_plot_class'] = 'Plot DataPlot(&display);\n'; + Blockly.Arduino.variables_['define_plot_class'] = 'const double TIMEFRAME = ' + TimeFrame + ';\n'; + Blockly.Arduino.setupCode_['sensebox_plot_setup'] = 'DataPlot.setTitle(' + Title + ');\nDataPlot.setXLabel(' + XLabel + ');\nDataPlot.setYLabel(' + YLabel + ');\nDataPlot.setXRange(' + XRange1 + ',' + XRange2 + ');\nDataPlot.setYRange(' + YRange1 + ',' + YRange2 + ');\nDataPlot.setXTick(' + XTick + ');\nDataPlot.setYTick(' + YTick + ');\nDataPlot.setXPrecision(0);\nDataPlot.setYPrecision(0);\n'; + var code = 'DataPlot.clear();' + code += 'double starttime = millis();\ndouble t = 0;\nwhile (t <= TIMEFRAME) {\nt = (millis() - starttime) / 1000.0;\nfloat value = ' + plotDisplay + ';\n'; + code += 'DataPlot.addDataPoint(t,value);\n}\n'; + return code; +}; + +Blockly.Arduino.sensebox_display_fillCircle = function () { + var x = Blockly.Arduino.valueToCode(this, 'X', Blockly.Arduino.ORDER_ATOMIC) || '0' + var y = Blockly.Arduino.valueToCode(this, 'Y', Blockly.Arduino.ORDER_ATOMIC) || '0' + var radius = Blockly.Arduino.valueToCode(this, 'Radius', Blockly.Arduino.ORDER_ATOMIC) || '0' + var fill = this.getFieldValue('FILL'); + if (fill == 'TRUE') { + var code = 'display.fillCircle(' + x + ',' + y + ',' + radius + ',1);\n'; + } + else { + var code = 'display.drawCircle(' + x + ',' + y + ',' + radius + ',1);\n'; + } + return code; +} + +Blockly.Arduino.sensebox_display_drawRectangle = function () { + var x = Blockly.Arduino.valueToCode(this, 'X', Blockly.Arduino.ORDER_ATOMIC) || '0' + var y = Blockly.Arduino.valueToCode(this, 'Y', Blockly.Arduino.ORDER_ATOMIC) || '0' + var width = Blockly.Arduino.valueToCode(this, 'width', Blockly.Arduino.ORDER_ATOMIC) || '0' + var height = Blockly.Arduino.valueToCode(this, 'height', Blockly.Arduino.ORDER_ATOMIC) || '0' + var fill = this.getFieldValue('FILL'); + if (fill == 'TRUE') { + var code = 'display.fillRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n'; + } + else { + var code = 'display.drawRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n'; + } + return code; +} \ No newline at end of file diff --git a/src/components/Blockly/generator/sensebox-web.js b/src/components/Blockly/generator/sensebox-web.js new file mode 100644 index 0000000..8727328 --- /dev/null +++ b/src/components/Blockly/generator/sensebox-web.js @@ -0,0 +1,25 @@ +import Blockly from 'blockly'; + + +/* Wifi connection and openSenseMap Blocks*/ +Blockly.Arduino.sensebox_wifi = function (block) { + var pw = this.getFieldValue('Password'); + var ssid = this.getFieldValue('SSID'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['define_network'] = 'Bee* b = new Bee();'; + if (pw === "") { + Blockly.Arduino.setupCode_['sensebox_network'] = 'b->connectToWifi("' + ssid + '");\ndelay(1000);'; + } else + Blockly.Arduino.setupCode_['sensebox_network'] = 'b->connectToWifi("' + ssid + '","' + pw + '");\ndelay(1000);'; + var code = ''; + return code; +}; + +Blockly.Arduino.sensebox_startap = function (block) { + var ssid = this.getFieldValue('SSID'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.definitions_['define_network'] = 'Bee* b = new Bee();'; + Blockly.Arduino.setupCode_['sensebox_network'] = 'b->startAP("' + ssid + '");' + var code = ''; + return code; +}; \ No newline at end of file diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js index 18ec1db..c7ec1a1 100644 --- a/src/components/Blockly/toolbox/Toolbox.js +++ b/src/components/Blockly/toolbox/Toolbox.js @@ -19,6 +19,120 @@ class Toolbox extends React.Component { + + + + + + + + + + + + 1 + + + + + 0 + + + + + 0 + + + + + + + + + + + + + + + + + + + 0 + + + + + 15 + + + + + 0 + + + + + 50 + + + + + 5 + + + + + 0 + + + + + 15 + + + + + + + 0 + + + + + 0 + + + + + 0 + + + + + + + 0 + + + + + 0 + + + + + 0 + + + + + 0 + + + + From 25aae52da3958bc4849516f97cd5973fdb1842d0 Mon Sep 17 00:00:00 2001 From: felixerdy Date: Fri, 31 Jul 2020 16:15:41 +0200 Subject: [PATCH 07/12] some styling --- src/App.js | 1 + src/components/Blockly/BlocklyComponent.css | 2 +- src/components/Blockly/BlocklyComponent.jsx | 4 +- src/components/CodeViewer.js | 6 +- src/components/WorkspaceStats.js | 81 ++++++++++++--------- 5 files changed, 57 insertions(+), 37 deletions(-) diff --git a/src/App.js b/src/App.js index 67e20d0..50afe39 100644 --- a/src/App.js +++ b/src/App.js @@ -17,6 +17,7 @@ const theme = createMuiTheme({ palette: { primary: { main: '#4EAF47', + contrastText: '#ffffff' }, secondary: { main: '#DDDDDD' diff --git a/src/components/Blockly/BlocklyComponent.css b/src/components/Blockly/BlocklyComponent.css index ce2c211..acc2ee2 100644 --- a/src/components/Blockly/BlocklyComponent.css +++ b/src/components/Blockly/BlocklyComponent.css @@ -2,6 +2,6 @@ height: 100%; min-height: 700px; width: 100%; - border: 1px solid #4EAF47; + /* border: 1px solid #4EAF47; */ position: relative; } diff --git a/src/components/Blockly/BlocklyComponent.jsx b/src/components/Blockly/BlocklyComponent.jsx index 50d8578..9d5696e 100644 --- a/src/components/Blockly/BlocklyComponent.jsx +++ b/src/components/Blockly/BlocklyComponent.jsx @@ -29,6 +29,8 @@ import locale from 'blockly/msg/en'; import 'blockly/blocks'; import Toolbox from './toolbox/Toolbox'; +import { Card } from '@material-ui/core'; + Blockly.setLocale(locale); @@ -66,7 +68,7 @@ class BlocklyComponent extends React.Component { return -
+ ; } diff --git a/src/components/CodeViewer.js b/src/components/CodeViewer.js index 0a62b12..aab9167 100644 --- a/src/components/CodeViewer.js +++ b/src/components/CodeViewer.js @@ -11,6 +11,8 @@ import { withStyles } from '@material-ui/core/styles'; import MuiAccordion from '@material-ui/core/Accordion'; import MuiAccordionSummary from '@material-ui/core/AccordionSummary'; import MuiAccordionDetails from '@material-ui/core/AccordionDetails'; +import { Card } from '@material-ui/core'; + const Accordion = withStyles((theme) => ({ root: { @@ -73,7 +75,7 @@ class CodeViewer extends Component { var curlyBrackets = '{ }'; var unequal = '<>'; return ( -
+ -
+
); }; } diff --git a/src/components/WorkspaceStats.js b/src/components/WorkspaceStats.js index 2317d79..098e02d 100644 --- a/src/components/WorkspaceStats.js +++ b/src/components/WorkspaceStats.js @@ -6,6 +6,8 @@ import * as Blockly from 'blockly/core'; import { withStyles } from '@material-ui/core/styles'; import Tooltip from '@material-ui/core/Tooltip'; +import Chip from '@material-ui/core/Chip'; +import Avatar from '@material-ui/core/Avatar'; import Typography from '@material-ui/core/Typography'; import { faPuzzlePiece, faTrash, faPlus, faPen, faArrowsAlt } from "@fortawesome/free-solid-svg-icons"; @@ -17,7 +19,7 @@ const styles = (theme) => ({ display: 'inline', marginLeft: '50px', padding: '3px 10px', - borderRadius: '25%' + // borderRadius: '25%' } }); @@ -27,44 +29,57 @@ class WorkspaceStats extends Component { const workspace = Blockly.getMainWorkspace(); const remainingBlocksInfinity = workspace ? workspace.remainingCapacity() !== Infinity : null; return ( -
- -
- - {workspace ? workspace.getAllBlocks().length : 0} -
+
+ + } + label={workspace ? workspace.getAllBlocks().length : 0}> + - -
- - - {this.props.create} -
+ + } + label={this.props.create}> + - -
- - - {this.props.change} -
+ + } + label={this.props.change}> + - -
- - - {this.props.move} -
+ + } + label={this.props.move}> + - -
- - - {this.props.delete} -
+ + } + label={this.props.delete}> + {remainingBlocksInfinity ? - - {workspace.remainingCapacity()} verbleibende Blöcke + + + : null}
); From 6678afbdff396f7a5b224b6dd53771860f7d194d Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 16:18:45 +0200 Subject: [PATCH 08/12] add map block --- src/components/Blockly/blocks/index.js | 1 + src/components/Blockly/blocks/loops.js | 2 + src/components/Blockly/blocks/map.js | 50 +++++++++++++++++++ src/components/Blockly/generator/index.js | 2 + src/components/Blockly/generator/map.js | 24 +++++++++ .../Blockly/generator/sensebox-display.js | 14 +++--- src/components/Blockly/toolbox/Toolbox.js | 2 +- 7 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 src/components/Blockly/blocks/map.js create mode 100644 src/components/Blockly/generator/map.js diff --git a/src/components/Blockly/blocks/index.js b/src/components/Blockly/blocks/index.js index d1ce014..8913b3b 100644 --- a/src/components/Blockly/blocks/index.js +++ b/src/components/Blockly/blocks/index.js @@ -8,6 +8,7 @@ import './sensebox-web'; import './sensebox-display'; import './io'; import './math'; +import './map'; import './procedures'; import './time'; diff --git a/src/components/Blockly/blocks/loops.js b/src/components/Blockly/blocks/loops.js index 5bc0123..5986b3e 100644 --- a/src/components/Blockly/blocks/loops.js +++ b/src/components/Blockly/blocks/loops.js @@ -1,5 +1,6 @@ import Blockly from 'blockly'; +import { getColour } from '../helpers/colour'; Blockly.defineBlocksWithJsonArray([ { @@ -44,6 +45,7 @@ Blockly.defineBlocksWithJsonArray([ inputsInline: false, previousStatement: null, nextStatement: null, + colour: getColour().loops, helpUrl: '%{BKY_CONTROLS_FOR_HELPURL}', extensions: ['contextMenu_newGetVariableBlock', 'controls_for_tooltip'], }, diff --git a/src/components/Blockly/blocks/map.js b/src/components/Blockly/blocks/map.js new file mode 100644 index 0000000..38b16df --- /dev/null +++ b/src/components/Blockly/blocks/map.js @@ -0,0 +1,50 @@ +/** + * @license Licensed under the Apache License, Version 2.0 (the "License"): + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * @fileoverview Block for the Arduino map functionality. + * The Arduino built in functions syntax can be found at: + * http://arduino.cc/en/Reference/HomePage + * + * TODO: This block can be improved to set the new range properly. + */ + + +import * as Blockly from 'blockly/core'; +import { getColour } from '../helpers/colour'; +import * as Types from '../helpers/types' + +Blockly.Blocks['base_map'] = { + /** + * Block for creating a the map function. + * @this Blockly.Block + */ + init: function () { + this.setHelpUrl('http://arduino.cc/en/Reference/map'); + this.setColour(getColour().math); + this.appendValueInput('NUM') + .appendField(Blockly.Msg.ARD_MAP) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('FMIN') + .appendField(Blockly.Msg.ARD_MAP_FROMMIN) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('FMAX') + .appendField(Blockly.Msg.ARD_MAP_FROMMAX) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('DMIN') + .appendField(Blockly.Msg.ARD_MAP_TOMIN) + .setCheck(Types.NUMBER.compatibleTypes); + this.appendValueInput('DMAX') + .appendField(Blockly.Msg.ARD_MAP_TOMAX) + .setCheck(Types.NUMBER.compatibleTypes); + this.setOutput(true); + this.setInputsInline(false); + this.setTooltip(Blockly.Msg.ARD_MAP_TIP); + }, + /** @return {string} The type of return value for the block, an integer. */ + getBlockType: function () { + return Types.NUMBER.typeId; + } +}; diff --git a/src/components/Blockly/generator/index.js b/src/components/Blockly/generator/index.js index d645206..5725e36 100644 --- a/src/components/Blockly/generator/index.js +++ b/src/components/Blockly/generator/index.js @@ -4,8 +4,10 @@ import './sensebox-sensors'; import './sensebox-telegram'; import './sensebox-osem'; import './sensebox-web'; +import './sensebox-display'; import './logic'; import './math'; +import './map'; import './io'; import './procedures'; import './time'; diff --git a/src/components/Blockly/generator/map.js b/src/components/Blockly/generator/map.js new file mode 100644 index 0000000..4cd3f64 --- /dev/null +++ b/src/components/Blockly/generator/map.js @@ -0,0 +1,24 @@ +import * as Blockly from 'blockly/core'; + + +/** + * Code generator for the map block. + * Arduino code: loop { map(x, 0, 1024, 0, y) } + * @param {!Blockly.Block} block Block to generate the code from. + * @return {array} Completed code with order of operation. + */ +Blockly.Arduino['base_map'] = function (block) { + var valueNum = Blockly.Arduino.valueToCode( + block, 'NUM', Blockly.Arduino.ORDER_NONE) || '0'; + var fromMin = Blockly.Arduino.valueToCode( + block, 'FMIN', Blockly.Arduino.ORDER_ATOMIC) || '0'; + var fromMax = Blockly.Arduino.valueToCode( + block, 'FMAX', Blockly.Arduino.ORDER_ATOMIC) || '0'; + var valueDmin = Blockly.Arduino.valueToCode( + block, 'DMIN', Blockly.Arduino.ORDER_ATOMIC) || '0'; + var valueDmax = Blockly.Arduino.valueToCode( + block, 'DMAX', Blockly.Arduino.ORDER_ATOMIC) || '0'; + + var code = 'map(' + valueNum + ',' + fromMin + ',' + fromMax + ',' + valueDmin + ',' + valueDmax + ')'; + return [code, Blockly.Arduino.ORDER_NONE]; +}; \ No newline at end of file diff --git a/src/components/Blockly/generator/sensebox-display.js b/src/components/Blockly/generator/sensebox-display.js index 5a83d8d..17f8542 100644 --- a/src/components/Blockly/generator/sensebox-display.js +++ b/src/components/Blockly/generator/sensebox-display.js @@ -61,30 +61,32 @@ Blockly.Arduino.sensebox_display_plotDisplay = function () { }; Blockly.Arduino.sensebox_display_fillCircle = function () { + let code = ''; var x = Blockly.Arduino.valueToCode(this, 'X', Blockly.Arduino.ORDER_ATOMIC) || '0' var y = Blockly.Arduino.valueToCode(this, 'Y', Blockly.Arduino.ORDER_ATOMIC) || '0' var radius = Blockly.Arduino.valueToCode(this, 'Radius', Blockly.Arduino.ORDER_ATOMIC) || '0' var fill = this.getFieldValue('FILL'); - if (fill == 'TRUE') { - var code = 'display.fillCircle(' + x + ',' + y + ',' + radius + ',1);\n'; + if (fill === 'TRUE') { + code = 'display.fillCircle(' + x + ',' + y + ',' + radius + ',1);\n'; } else { - var code = 'display.drawCircle(' + x + ',' + y + ',' + radius + ',1);\n'; + code = 'display.drawCircle(' + x + ',' + y + ',' + radius + ',1);\n'; } return code; } Blockly.Arduino.sensebox_display_drawRectangle = function () { + let code = ''; var x = Blockly.Arduino.valueToCode(this, 'X', Blockly.Arduino.ORDER_ATOMIC) || '0' var y = Blockly.Arduino.valueToCode(this, 'Y', Blockly.Arduino.ORDER_ATOMIC) || '0' var width = Blockly.Arduino.valueToCode(this, 'width', Blockly.Arduino.ORDER_ATOMIC) || '0' var height = Blockly.Arduino.valueToCode(this, 'height', Blockly.Arduino.ORDER_ATOMIC) || '0' var fill = this.getFieldValue('FILL'); - if (fill == 'TRUE') { - var code = 'display.fillRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n'; + if (fill === 'TRUE') { + code = 'display.fillRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n'; } else { - var code = 'display.drawRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n'; + code = 'display.drawRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n'; } return code; } \ No newline at end of file diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js index c7ec1a1..943ff0e 100644 --- a/src/components/Blockly/toolbox/Toolbox.js +++ b/src/components/Blockly/toolbox/Toolbox.js @@ -240,7 +240,7 @@ class Toolbox extends React.Component { - {/* */} + From dd874a238492d0d170afe558e39b264f54ec38bb Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 16:37:09 +0200 Subject: [PATCH 09/12] add LoRa Blocks --- src/components/Blockly/blocks/index.js | 1 + .../Blockly/blocks/sensebox-lora.js | 253 ++++++++++ src/components/Blockly/generator/generator.js | 12 +- src/components/Blockly/generator/index.js | 1 + .../Blockly/generator/sensebox-lora.js | 431 ++++++++++++++++++ src/components/Blockly/toolbox/Toolbox.js | 20 + 6 files changed, 717 insertions(+), 1 deletion(-) create mode 100644 src/components/Blockly/blocks/sensebox-lora.js create mode 100644 src/components/Blockly/generator/sensebox-lora.js diff --git a/src/components/Blockly/blocks/index.js b/src/components/Blockly/blocks/index.js index 8913b3b..b35391f 100644 --- a/src/components/Blockly/blocks/index.js +++ b/src/components/Blockly/blocks/index.js @@ -6,6 +6,7 @@ import './sensebox-telegram'; import './sensebox-osem'; import './sensebox-web'; import './sensebox-display'; +import './sensebox-lora'; import './io'; import './math'; import './map'; diff --git a/src/components/Blockly/blocks/sensebox-lora.js b/src/components/Blockly/blocks/sensebox-lora.js new file mode 100644 index 0000000..170cc45 --- /dev/null +++ b/src/components/Blockly/blocks/sensebox-lora.js @@ -0,0 +1,253 @@ +import * as Blockly from 'blockly/core'; +import { getColour } from '../helpers/colour'; + + +/* +----------------------------------LoRa-------------------------------------------------- +*/ + +Blockly.Blocks['sensebox_lora_initialize_otaa'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_init_otaa_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField("Initialize LoRa (OTAA)"); + + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_device_id) + .appendField(new Blockly.FieldTextInput("DEVICE ID"), "DEVICEID"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_app_id) + .appendField(new Blockly.FieldTextInput("APP ID"), "APPID"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_app_key) + .appendField(new Blockly.FieldTextInput("APP KEY"), "APPKEY"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_interval) + .appendField(new Blockly.FieldTextInput("5"), "INTERVAL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, +}; + +Blockly.Blocks['sensebox_lora_initialize_abp'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_init_abp_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendDummyInput() + .appendField("Initialize LoRa (ABP)"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_nwskey_id) + .appendField(new Blockly.FieldTextInput("NWSKEY"), "NWSKEY"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_appskey_id) + .appendField(new Blockly.FieldTextInput("APPSKEY"), "APPSKEY"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_devaddr_id) + .appendField(new Blockly.FieldTextInput("DEVADDR"), "DEVADDR"); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_interval) + .appendField(new Blockly.FieldTextInput("5"), "INTERVAL"); + // this.appendStatementInput('DO') + // .appendField(Blockly.Msg.senseBox_measurements) + // .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, +}; + +Blockly.Blocks['sensebox_lora_message_send'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_message_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.senseBox_LoRa_send_message) + .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; + +Blockly.Blocks['sensebox_send_lora_sensor_value'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_sensor_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('Value') + .appendField(Blockly.Msg.senseBox_measurement) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField("Bytes") + .appendField(new Blockly.FieldTextInput("2"), "MESSAGE_BYTES"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + /** + * Called whenever anything on the workspace changes. + * Add warning if block is not nested inside a the correct loop. + * @param {!Blockly.Events.Abstract} e Change event. + * @this Blockly.Block + */ + onchange: function (e) { + var legal = false; + // Is the block nested in a loop? + var block = this; + do { + if (this.LOOP_TYPES.indexOf(block.type) !== -1) { + legal = true; + break; + } + block = block.getSurroundParent(); + } while (block); + if (legal) { + this.setWarningText(null); + } else { + this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING); + } + }, + LOOP_TYPES: ['sensebox_lora_message_send'], +}; + +Blockly.Blocks['sensebox_lora_cayenne_send'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendStatementInput('DO') + .appendField(Blockly.Msg.senseBox_LoRa_send_cayenne) + .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + } +}; +Blockly.Blocks['sensebox_lora_cayenne_temperature'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_temperature_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('Value') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_temperature) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_channel) + .appendField(new Blockly.FieldTextInput("1"), "CHANNEL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ['sensebox_lora_cayenne_send'], +}; +Blockly.Blocks['sensebox_lora_cayenne_humidity'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_humidity_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('Value') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_humidity) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_channel) + .appendField(new Blockly.FieldTextInput("1"), "CHANNEL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ['sensebox_lora_cayenne_send'], +}; +Blockly.Blocks['sensebox_lora_cayenne_pressure'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_pressure_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('Value') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_pressure) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_channel) + .appendField(new Blockly.FieldTextInput("1"), "CHANNEL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ['sensebox_lora_cayenne_send'], +}; +Blockly.Blocks['sensebox_lora_cayenne_luminosity'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_luminosity_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('Value') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_luminosity) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_channel) + .appendField(new Blockly.FieldTextInput("1"), "CHANNEL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ['sensebox_lora_cayenne_send'], +}; +Blockly.Blocks['sensebox_lora_cayenne_sensor'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_analog_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('Value') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_analog) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_channel) + .appendField(new Blockly.FieldTextInput("1"), "CHANNEL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ['sensebox_lora_cayenne_send'], +}; +Blockly.Blocks['sensebox_lora_cayenne_accelerometer'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_gyros_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('X') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_x) + this.appendValueInput('Y') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_y) + this.appendValueInput('Z') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_z) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_channel) + .appendField(new Blockly.FieldTextInput("1"), "CHANNEL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ['sensebox_lora_cayenne_send'], +}; +Blockly.Blocks['sensebox_lora_cayenne_gps'] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_LoRa_cayenne_gps_tip); + this.setHelpUrl(''); + this.setColour(getColour().sensebox); + this.appendValueInput('LAT') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_lat) + this.appendValueInput('LNG') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_lng) + this.appendValueInput('ALT') + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_alt) + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField(Blockly.Msg.senseBox_LoRa_cayenne_channel) + .appendField(new Blockly.FieldTextInput("1"), "CHANNEL"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + LOOP_TYPES: ['sensebox_lora_cayenne_send'], +}; diff --git a/src/components/Blockly/generator/generator.js b/src/components/Blockly/generator/generator.js index 8b5808b..7ff0fd4 100644 --- a/src/components/Blockly/generator/generator.js +++ b/src/components/Blockly/generator/generator.js @@ -109,6 +109,9 @@ Blockly['Arduino'].init = function (workspace) { // creates a list of code for the loop to be runned once Blockly['Arduino'].loopCodeOnce_ = Object.create(null) + // creates a list of code for the loop to be runned once + Blockly['Arduino'].codeFunctions_ = Object.create(null) + // creates a list of code variables Blockly['Arduino'].variables_ = Object.create(null) @@ -192,7 +195,8 @@ Blockly['Arduino'].init = function (workspace) { */ Blockly['Arduino'].finish = function (code) { let libraryCode = ''; - let variablesCode = '' + let variablesCode = ''; + let codeFunctions = ''; let functionsCode = ''; let definitionsCode = ''; let loopCodeOnce = ''; @@ -216,6 +220,10 @@ Blockly['Arduino'].finish = function (code) { loopCodeOnce += Blockly['Arduino'].loopCodeOnce_[key] + '\n'; } + for (const key in Blockly['Arduino'].codeFunctions_) { + codeFunctions += Blockly['Arduino'].codeFunctions_[key] + '\n'; + } + for (const key in Blockly['Arduino'].functionNames_) { functionsCode += Blockly['Arduino'].functionNames_[key] + '\n'; } @@ -240,6 +248,8 @@ Blockly['Arduino'].finish = function (code) { '\n' + definitionsCode + '\n' + + codeFunctions + + '\n' + Blockly['Arduino'].variablesInitCode_ + '\n' + functionsCode + diff --git a/src/components/Blockly/generator/index.js b/src/components/Blockly/generator/index.js index 5725e36..b86e0df 100644 --- a/src/components/Blockly/generator/index.js +++ b/src/components/Blockly/generator/index.js @@ -5,6 +5,7 @@ import './sensebox-telegram'; import './sensebox-osem'; import './sensebox-web'; import './sensebox-display'; +import './sensebox-lora'; import './logic'; import './math'; import './map'; diff --git a/src/components/Blockly/generator/sensebox-lora.js b/src/components/Blockly/generator/sensebox-lora.js new file mode 100644 index 0000000..6892210 --- /dev/null +++ b/src/components/Blockly/generator/sensebox-lora.js @@ -0,0 +1,431 @@ +import * as Blockly from 'blockly/core'; + + +Blockly.Arduino.sensebox_lora_initialize_otaa = function (block) { + var deivceID = this.getFieldValue('DEVICEID'); + var appID = this.getFieldValue('APPID'); + var appKey = this.getFieldValue('APPKEY'); + var interval = this.getFieldValue('INTERVAL'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.libraries_['library_spi'] = '#include '; + Blockly.Arduino.libraries_['library_lmic'] = '#include '; + Blockly.Arduino.libraries_['library_hal'] = '#include '; + Blockly.Arduino.definitions_['define_LoRaVariablesOTAA'] = ` + static const u1_t PROGMEM APPEUI[8]= `+ appID + ` ; + void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI , 8);} + + static const u1_t PROGMEM DEVEUI[8]= `+ deivceID + `; + void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI , 8);} + + // This key should be in big endian format (or, since it is not really a + // number but a block of memory, endianness does not really apply). In + // practice, a key taken from ttnctl can be copied as-is. + // The key shown here is the semtech default key. + static const u1_t PROGMEM APPKEY[16] = `+ appKey + `; + void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY , 16);} + + static osjob_t sendjob; + + // Schedule TX every this many seconds (might become longer due to duty + // cycle limitations). + const unsigned TX_INTERVAL = ${interval * 60}; + + // Pin mapping + const lmic_pinmap lmic_pins = { + .nss = PIN_XB1_CS, + .rxtx = LMIC_UNUSED_PIN, + .rst = LMIC_UNUSED_PIN, + .dio = {PIN_XB1_INT, PIN_XB1_INT, LMIC_UNUSED_PIN}, + };`; + + Blockly.Arduino.codeFunctions_['functions_initLora'] = ` + void initLora() { + delay(2000); + // LMIC init + os_init(); + // Reset the MAC state. Session and pending data transfers will be discarded. + LMIC_reset(); + + // Start job (sending automatically starts OTAA too) + do_send(&sendjob); + }` + + Blockly.Arduino.codeFunctions_['functions_onEvent'] = ` + void onEvent (ev_t ev) { + Serial.print(os_getTime()); + Serial.print(": "); + switch(ev) { + case EV_SCAN_TIMEOUT: + Serial.println(F("EV_SCAN_TIMEOUT")); + break; + case EV_BEACON_FOUND: + Serial.println(F("EV_BEACON_FOUND")); + break; + case EV_BEACON_MISSED: + Serial.println(F("EV_BEACON_MISSED")); + break; + case EV_BEACON_TRACKED: + Serial.println(F("EV_BEACON_TRACKED")); + break; + case EV_JOINING: + Serial.println(F("EV_JOINING")); + break; + case EV_JOINED: + Serial.println(F("EV_JOINED")); + + // Disable link check validation (automatically enabled + // during join, but not supported by TTN at this time). + LMIC_setLinkCheckMode(0); + break; + case EV_RFU1: + Serial.println(F("EV_RFU1")); + break; + case EV_JOIN_FAILED: + Serial.println(F("EV_JOIN_FAILED")); + break; + case EV_REJOIN_FAILED: + Serial.println(F("EV_REJOIN_FAILED")); + break; + break; + case EV_TXCOMPLETE: + Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); + if (LMIC.txrxFlags & TXRX_ACK) + Serial.println(F("Received ack")); + if (LMIC.dataLen) { + Serial.println(F("Received ")); + Serial.println(LMIC.dataLen); + Serial.println(F(" bytes of payload")); + } + // Schedule next transmission + os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); + break; + case EV_LOST_TSYNC: + Serial.println(F("EV_LOST_TSYNC")); + break; + case EV_RESET: + Serial.println(F("EV_RESET")); + break; + case EV_RXCOMPLETE: + // data received in ping slot + Serial.println(F("EV_RXCOMPLETE")); + break; + case EV_LINK_DEAD: + Serial.println(F("EV_LINK_DEAD")); + break; + case EV_LINK_ALIVE: + Serial.println(F("EV_LINK_ALIVE")); + break; + default: + Serial.println(F("Unknown event")); + break; + } + }`; + Blockly.Arduino.setupCode_['initLora'] = 'initLora();'; + Blockly.Arduino.setupCode_['serial.begin'] = 'Serial.begin(9600);'; + var code = '' + return code; +}; + +Blockly.Arduino.sensebox_lora_message_send = function (block) { + Blockly.Arduino.libraries_['library_lora_message'] = '#include '; + var lora_sensor_values = Blockly.Arduino.statementToCode(block, 'DO'); + Blockly.Arduino.functionNames_['functions_do_send'] = ` + void do_send(osjob_t* j){ + // Check if there is not a current TX/RX job running + if (LMIC.opmode & OP_TXRXPEND) { + Serial.println(F("OP_TXRXPEND, not sending")); + } else { + LoraMessage message; + ${lora_sensor_values} + + // Prepare upstream data transmission at the next possible time. + LMIC_setTxData2(1, message.getBytes(), message.getLength(), 0); + Serial.println(F("Packet queued")); + } + // Next TX is scheduled after TX_COMPLETE event. + }`; + Blockly.Arduino.loopCodeOnce_['os_runloop'] = 'os_runloop_once();' + return '' +} + +/** + * Block send Data to TTN + */ +Blockly.Arduino.sensebox_send_lora_sensor_value = function (block) { + const reading = Blockly.Arduino.valueToCode(this, 'Value', Blockly.Arduino.ORDER_ATOMIC) || '"Keine Eingabe"'; + var messageBytes = this.getFieldValue('MESSAGE_BYTES'); + var code = '' + switch (Number(messageBytes)) { + case 1: + code = `message.addUint8(${reading});\n` + break; + case 2: + code = `message.addUint16(${reading});\n` + break; + case 3: + code = `message.addUint8(${reading}); + message.addUint16(${reading} >> 8);\n` + break; + default: + code = `message.addUint16(${reading});\n` + } + return code; +}; + +Blockly.Arduino.sensebox_lora_cayenne_send = function (block) { + Blockly.Arduino.libraries_['library_cayene'] = '#include '; + Blockly.Arduino.variables_['variable_cayenne'] = 'CayenneLPP lpp(51);' + var lora_sensor_values = Blockly.Arduino.statementToCode(block, 'DO'); + Blockly.Arduino.functionNames_['functions_do_send'] = ` + void do_send(osjob_t* j){ + // Check if there is not a current TX/RX job running + if (LMIC.opmode & OP_TXRXPEND) { + Serial.println(F("OP_TXRXPEND, not sending")); + } else { + lpp.reset(); + ${lora_sensor_values} + + // Prepare upstream data transmission at the next possible time. + LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0); + Serial.println(F("Packet queued")); + } + // Next TX is scheduled after TX_COMPLETE event. + }`; + Blockly.Arduino.loopCodeOnce_['os_runloop'] = 'os_runloop_once();' + return ''; +} + +Blockly.Arduino.sensebox_lora_initialize_abp = function (block) { + var nwskey = this.getFieldValue('NWSKEY'); + var appskey = this.getFieldValue('APPSKEY'); + var devaddr = this.getFieldValue('DEVADDR'); + var interval = this.getFieldValue('INTERVAL'); + Blockly.Arduino.libraries_['library_senseBoxMCU'] = '#include "SenseBoxMCU.h"'; + Blockly.Arduino.libraries_['library_spi'] = '#include '; + Blockly.Arduino.libraries_['library_lmic'] = '#include '; + Blockly.Arduino.libraries_['library_hal'] = '#include '; + Blockly.Arduino.definitions_['define_LoRaVariablesABP'] = ` + // LoRaWAN NwkSKey, network session key + // This is the default Semtech key, which is used by the early prototype TTN + // network. + static const PROGMEM u1_t NWKSKEY[16] = ${nwskey}; + + // LoRaWAN AppSKey, application session key + // This is the default Semtech key, which is used by the early prototype TTN + // network. + static const u1_t PROGMEM APPSKEY[16] = ${appskey}; + + // LoRaWAN end-device address (DevAddr) + static const u4_t DEVADDR = 0x${devaddr}; + + // These callbacks are only used in over-the-air activation, so they are + // left empty here (we cannot leave them out completely unless + // DISABLE_JOIN is set in config.h, otherwise the linker will complain). + void os_getArtEui (u1_t* buf) { } + void os_getDevEui (u1_t* buf) { } + void os_getDevKey (u1_t* buf) { } + + static osjob_t sendjob; + + // Schedule TX every this many seconds (might become longer due to duty + // cycle limitations). + const unsigned TX_INTERVAL = ${interval * 60}; + + // Pin mapping + const lmic_pinmap lmic_pins = { + .nss = PIN_XB1_CS, + .rxtx = LMIC_UNUSED_PIN, + .rst = LMIC_UNUSED_PIN, + .dio = {PIN_XB1_INT, PIN_XB1_INT, LMIC_UNUSED_PIN}, + };`; + + Blockly.Arduino.codeFunctions_['functions_initLora'] = ` + void initLora() { + delay(2000); + // LMIC init + os_init(); + // Reset the MAC state. Session and pending data transfers will be discarded. + LMIC_reset(); + + // Set static session parameters. Instead of dynamically establishing a session + // by joining the network, precomputed session parameters are be provided. + #ifdef PROGMEM + // On AVR, these values are stored in flash and only copied to RAM + // once. Copy them to a temporary buffer here, LMIC_setSession will + // copy them into a buffer of its own again. + uint8_t appskey[sizeof(APPSKEY)]; + uint8_t nwkskey[sizeof(NWKSKEY)]; + memcpy_P(appskey, APPSKEY, sizeof(APPSKEY)); + memcpy_P(nwkskey, NWKSKEY, sizeof(NWKSKEY)); + LMIC_setSession (0x1, DEVADDR, nwkskey, appskey); + #else + // If not running an AVR with PROGMEM, just use the arrays directly + LMIC_setSession (0x1, DEVADDR, NWKSKEY, APPSKEY); + #endif + + #if defined(CFG_eu868) + // Set up the channels used by the Things Network, which corresponds + // to the defaults of most gateways. Without this, only three base + // channels from the LoRaWAN specification are used, which certainly + // works, so it is good for debugging, but can overload those + // frequencies, so be sure to configure the full frequency range of + // your network here (unless your network autoconfigures them). + // Setting up channels should happen after LMIC_setSession, as that + // configures the minimal channel set. + // NA-US channels 0-71 are configured automatically + LMIC_setupChannel(0, 868100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band + LMIC_setupChannel(1, 868300000, DR_RANGE_MAP(DR_SF12, DR_SF7B), BAND_CENTI); // g-band + LMIC_setupChannel(2, 868500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band + LMIC_setupChannel(3, 867100000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band + LMIC_setupChannel(4, 867300000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band + LMIC_setupChannel(5, 867500000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band + LMIC_setupChannel(6, 867700000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band + LMIC_setupChannel(7, 867900000, DR_RANGE_MAP(DR_SF12, DR_SF7), BAND_CENTI); // g-band + LMIC_setupChannel(8, 868800000, DR_RANGE_MAP(DR_FSK, DR_FSK), BAND_MILLI); // g2-band + // TTN defines an additional channel at 869.525Mhz using SF9 for class B + // devices' ping slots. LMIC does not have an easy way to define set this + // frequency and support for class B is spotty and untested, so this + // frequency is not configured here. + #elif defined(CFG_us915) + // NA-US channels 0-71 are configured automatically + // but only one group of 8 should (a subband) should be active + // TTN recommends the second sub band, 1 in a zero based count. + // https://github.com/TheThingsNetwork/gateway-conf/blob/master/US-global_conf.json + LMIC_selectSubBand(1); + #endif + + // Disable link check validation + LMIC_setLinkCheckMode(0); + + // TTN uses SF9 for its RX2 window. + LMIC.dn2Dr = DR_SF9; + + // Set data rate and transmit power for uplink (note: txpow seems to be ignored by the library) + LMIC_setDrTxpow(DR_SF7,14); + + // Start job + do_send(&sendjob); + }` + + Blockly.Arduino.codeFunctions_['functions_onEvent'] = ` + void onEvent (ev_t ev) { + Serial.print(os_getTime()); + Serial.print(": "); + switch(ev) { + case EV_SCAN_TIMEOUT: + Serial.println(F("EV_SCAN_TIMEOUT")); + break; + case EV_BEACON_FOUND: + Serial.println(F("EV_BEACON_FOUND")); + break; + case EV_BEACON_MISSED: + Serial.println(F("EV_BEACON_MISSED")); + break; + case EV_BEACON_TRACKED: + Serial.println(F("EV_BEACON_TRACKED")); + break; + case EV_JOINING: + Serial.println(F("EV_JOINING")); + break; + case EV_JOINED: + Serial.println(F("EV_JOINED")); + break; + case EV_RFU1: + Serial.println(F("EV_RFU1")); + break; + case EV_JOIN_FAILED: + Serial.println(F("EV_JOIN_FAILED")); + break; + case EV_REJOIN_FAILED: + Serial.println(F("EV_REJOIN_FAILED")); + break; + case EV_TXCOMPLETE: + Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); + if (LMIC.txrxFlags & TXRX_ACK) + Serial.println(F("Received ack")); + if (LMIC.dataLen) { + Serial.println(F("Received ")); + Serial.println(LMIC.dataLen); + Serial.println(F(" bytes of payload")); + } + // Schedule next transmission + os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); + break; + case EV_LOST_TSYNC: + Serial.println(F("EV_LOST_TSYNC")); + break; + case EV_RESET: + Serial.println(F("EV_RESET")); + break; + case EV_RXCOMPLETE: + // data received in ping slot + Serial.println(F("EV_RXCOMPLETE")); + break; + case EV_LINK_DEAD: + Serial.println(F("EV_LINK_DEAD")); + break; + case EV_LINK_ALIVE: + Serial.println(F("EV_LINK_ALIVE")); + break; + default: + Serial.println(F("Unknown event")); + break; + } + }`; + Blockly.Arduino.setupCode_['initLora'] = 'initLora();'; + Blockly.Arduino.setupCode_['serial.begin'] = 'Serial.begin(9600);'; + return ''; +} + +Blockly.Arduino.sensebox_lora_cayenne_temperature = function (block) { + var temperature = Blockly.Arduino.valueToCode(this, 'Value', Blockly.Arduino.ORDER_ATOMIC) || 0 + var channel = this.getFieldValue('CHANNEL'); + var code = `lpp.addTemperature(${channel}, ${temperature});\n`; + return code; +} + +Blockly.Arduino.sensebox_lora_cayenne_humidity = function (block) { + var humidity = Blockly.Arduino.valueToCode(this, 'Value', Blockly.Arduino.ORDER_ATOMIC) || 0 + var channel = this.getFieldValue('CHANNEL'); + var code = `lpp.addRelativeHumidity(${channel}, ${humidity});\n`; + return code; +} + +Blockly.Arduino.sensebox_lora_cayenne_pressure = function (block) { + var pressure = Blockly.Arduino.valueToCode(this, 'Value', Blockly.Arduino.ORDER_ATOMIC) || 0 + var channel = this.getFieldValue('CHANNEL'); + var code = `lpp.addBarometricPressure(${channel}, ${pressure});\n`; + return code; +} + +Blockly.Arduino.sensebox_lora_cayenne_luminosity = function (block) { + var luminosity = Blockly.Arduino.valueToCode(this, 'Value', Blockly.Arduino.ORDER_ATOMIC) || 0 + var channel = this.getFieldValue('CHANNEL'); + var code = `lpp.addLuminosity(${channel}, ${luminosity});\n`; + return code; +} + +Blockly.Arduino.sensebox_lora_cayenne_sensor = function (block) { + var sensorValue = Blockly.Arduino.valueToCode(this, 'Value', Blockly.Arduino.ORDER_ATOMIC) || 0 + var channel = this.getFieldValue('CHANNEL'); + var code = `lpp.addAnalogInput(${channel}, ${sensorValue});\n`; + return code; +} + +Blockly.Arduino.sensebox_lora_cayenne_accelerometer = function (block) { + var x = Blockly.Arduino.valueToCode(this, 'X', Blockly.Arduino.ORDER_ATOMIC) || 0 + var y = Blockly.Arduino.valueToCode(this, 'Y', Blockly.Arduino.ORDER_ATOMIC) || 0 + var z = Blockly.Arduino.valueToCode(this, 'Z', Blockly.Arduino.ORDER_ATOMIC) || 0 + var channel = this.getFieldValue('CHANNEL'); + var code = `lpp.addAccelerometer(${channel}, ${x}, ${y}, ${z});\n`; + return code; +} + +Blockly.Arduino.sensebox_lora_cayenne_gps = function (block) { + var lat = Blockly.Arduino.valueToCode(this, 'LAT', Blockly.Arduino.ORDER_ATOMIC) || 0 + var lng = Blockly.Arduino.valueToCode(this, 'LNG', Blockly.Arduino.ORDER_ATOMIC) || 0 + var alt = Blockly.Arduino.valueToCode(this, 'ALT', Blockly.Arduino.ORDER_ATOMIC) || 0 + var channel = this.getFieldValue('CHANNEL'); + var code = `lpp.addGPS(${channel}, ${lat}, ${lng}, ${alt});\n` + return code; +} \ No newline at end of file diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js index 943ff0e..9cadec6 100644 --- a/src/components/Blockly/toolbox/Toolbox.js +++ b/src/components/Blockly/toolbox/Toolbox.js @@ -142,6 +142,26 @@ class Toolbox extends React.Component { + + + + + + + + + + + + + + + + + + + + From 6e56054d1d22ec1a99c7a6ab0a82536a2fe668c8 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 16:42:41 +0200 Subject: [PATCH 10/12] remove typography warning --- src/components/WorkspaceStats.js | 55 ++++++++++++++++---------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/components/WorkspaceStats.js b/src/components/WorkspaceStats.js index 098e02d..5bbf8d7 100644 --- a/src/components/WorkspaceStats.js +++ b/src/components/WorkspaceStats.js @@ -1,4 +1,4 @@ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; @@ -8,7 +8,6 @@ import { withStyles } from '@material-ui/core/styles'; import Tooltip from '@material-ui/core/Tooltip'; import Chip from '@material-ui/core/Chip'; import Avatar from '@material-ui/core/Avatar'; -import Typography from '@material-ui/core/Typography'; import { faPuzzlePiece, faTrash, faPlus, faPen, faArrowsAlt } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -29,55 +28,55 @@ class WorkspaceStats extends Component { const workspace = Blockly.getMainWorkspace(); const remainingBlocksInfinity = workspace ? workspace.remainingCapacity() !== Infinity : null; return ( -
+
- } + } label={workspace ? workspace.getAllBlocks().length : 0}> - } + avatar={} label={this.props.create}> - } + avatar={} label={this.props.change}> - } + } label={this.props.move}> - } + } label={this.props.delete}> {remainingBlocksInfinity ? - : null} @@ -102,4 +101,4 @@ const mapStateToProps = state => ({ worskpaceChange: state.workspace.change }); -export default connect(mapStateToProps, null)(withStyles(styles, {withTheme: true})(WorkspaceStats)); +export default connect(mapStateToProps, null)(withStyles(styles, { withTheme: true })(WorkspaceStats)); From fd4afa9e60a2c5d6c46fb5897de1dc68fbefa7ce Mon Sep 17 00:00:00 2001 From: felixerdy Date: Mon, 3 Aug 2020 15:48:33 +0200 Subject: [PATCH 11/12] cleanup --- src/components/WorkspaceStats.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/WorkspaceStats.js b/src/components/WorkspaceStats.js index 5bbf8d7..1ca2bff 100644 --- a/src/components/WorkspaceStats.js +++ b/src/components/WorkspaceStats.js @@ -33,16 +33,14 @@ class WorkspaceStats extends Component { } label={workspace ? workspace.getAllBlocks().length : 0}> - + } label={this.props.create}> @@ -51,7 +49,6 @@ class WorkspaceStats extends Component { } label={this.props.change}> From ddd3fa1fcf7ac5cbfdd36d1de56951070cdbc392 Mon Sep 17 00:00:00 2001 From: felixerdy Date: Mon, 3 Aug 2020 16:38:18 +0200 Subject: [PATCH 12/12] online compiling --- .env | 2 ++ src/components/WorkspaceFunc.js | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..8a24119 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +REACT_APP_COMPILER_URL=https://compiler.sensebox.de +REACT_APP_BOARD=sensebox-mcu diff --git a/src/components/WorkspaceFunc.js b/src/components/WorkspaceFunc.js index 2bf4c11..fae6d5c 100644 --- a/src/components/WorkspaceFunc.js +++ b/src/components/WorkspaceFunc.js @@ -30,6 +30,29 @@ class WorkspaceFunc extends Component { this.setState({ open: !this.state }); } + compile = () => { + const data = { + "board": process.env.REACT_APP_BOARD, + "sketch": this.props.arduino + }; + + fetch(`${process.env.REACT_APP_COMPILER_URL}/compile`, { + method: "POST", + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify(data) + }) + .then(response => response.json()) + .then(data => { + console.log(data) + this.download(data.data.id) + }); + } + + download = (id) => { + const filename = 'sketch' + window.open(`${process.env.REACT_APP_COMPILER_URL}/download?id=${id}&board=${process.env.REACT_APP_BOARD}&filename=${filename}`, '_self'); + } + render() { return (
@@ -51,6 +74,9 @@ class WorkspaceFunc extends Component { Get XML Code +
); };