From 440622a66c557e3658c740c82681275b59919a0c Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 31 Jul 2020 11:10:22 +0200 Subject: [PATCH] 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 = {