Merge pull request #2 from sensebox/add-new-blocks

Add new blocks
This commit is contained in:
Delucse 2020-08-10 09:06:50 +02:00 committed by GitHub
commit c009674c46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 4127 additions and 215 deletions

2
.env Normal file
View File

@ -0,0 +1,2 @@
REACT_APP_COMPILER_URL=https://compiler.sensebox.de
REACT_APP_BOARD=sensebox-mcu

View File

@ -17,6 +17,7 @@ const theme = createMuiTheme({
palette: {
primary: {
main: '#4EAF47',
contrastText: '#ffffff'
},
secondary: {
main: '#DDDDDD'

View File

@ -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) => {

View File

@ -1,6 +1,7 @@
#blocklyDiv {
height: 100%;
min-height: 500px;
min-height: 700px;
width: 100%;
border: 1px solid #4EAF47;
/* border: 1px solid #4EAF47; */
position: relative;
}

View File

@ -25,10 +25,14 @@ 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);
import { Card } from '@material-ui/core';
Blockly.setLocale(locale);
class BlocklyComponent extends React.Component {
constructor(props) {
@ -61,13 +65,11 @@ class BlocklyComponent extends React.Component {
}
render() {
const { children } = this.props;
return <React.Fragment>
<div ref={this.blocklyDiv} id="blocklyDiv" />
<xml xmlns="https://developers.google.com/blockly/xml" is="blockly" style={{ display: 'none' }} ref={this.toolbox}>
{children}
</xml>
<Card ref={this.blocklyDiv} id="blocklyDiv" />
<Toolbox toolbox={this.toolbox} />
</React.Fragment>;
}
}

View File

@ -2,20 +2,20 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { onChangeWorkspace } from '../../actions/workspaceActions';
import BlocklyComponent, { Block, Value, Field, Shadow, Category } from './';
import * as De from './msg/de';
import BlocklyComponent 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 './blocks/index';
import './generator/index';
class BlocklyWindow extends Component {
constructor(props) {
super(props);
this.simpleWorkspace = React.createRef();
Blockly.setLocale(De);
}
componentDidMount() {
@ -23,6 +23,7 @@ class BlocklyWindow extends Component {
this.props.onChangeWorkspace({});
workspace.addChangeListener((event) => {
this.props.onChangeWorkspace(event);
Blockly.Events.disableOrphans(event);
});
}
@ -31,10 +32,11 @@ class BlocklyWindow extends Component {
<BlocklyComponent ref={this.simpleWorkspace}
readOnly={false}
trashcan={true}
renderer='zelos'
zoom={{ // https://developers.google.com/blockly/guides/configure/web/zoom
controls: true,
wheel: true,
startScale: 1.0,
wheel: false,
startScale: 0.8,
maxScale: 3,
minScale: 0.3,
scaleSpeed: 1.2
@ -51,28 +53,11 @@ class BlocklyWindow extends Component {
drag: true,
wheel: false
}}
initialXml={''}
initialXml={`<xml xmlns="https://developers.google.com/blockly/xml">
<block type="arduino_functions" id="QWW|$jB8+*EL;}|#uA" x="27" y="16"></block></xml>`}
>
<Category name="loops" >
<Block type="controls_for" />
<Block type="controls_repeat_ext" />
<Block type="controls_whileUntil" />
</Category>
<Category name="senseBox" colour="120" >
<Category name="Sensoren" colour="120" >
<Block type="sensebox_sensor_temp_hum"></Block>
</Category>
<Block type="sensebox_telegram" />
</Category>
<Category name="Logic" colour="#b063c5">
<Block type="control_if"></Block>
<Block type="controls_ifelse"></Block>
<Block type="logic_compare"></Block>
<Block type="logic_operation"></Block>
<Block type="logic_negate"></Block>
<Block type="logic_boolean"></Block>
</Category>
</BlocklyComponent>
</BlocklyComponent >
);
};
}

View File

@ -1,4 +1,17 @@
import './loops';
import './sensebox';
import './logic';
import './sensebox-sensors';
import './sensebox-sensors';
import './sensebox-telegram';
import './sensebox-osem';
import './sensebox-web';
import './sensebox-display';
import './sensebox-lora';
import './io';
import './math';
import './map';
import './procedures';
import './time';
import '../helpers/types'

View File

@ -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 Blockly from 'blockly/core';
import { selectedBoard } from '../helpers/board'
import * as Types from '../helpers/types'
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(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(
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 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(
selectedBoard().builtinLed), 'BUILT_IN_LED')
.appendField(Blockly.Msg.ARD_WRITE_TO)
.setCheck(Types.BOOLEAN.compatibleTypes);
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 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(
selectedBoard().pwmPins), 'PIN')
.appendField(Blockly.Msg.ARD_WRITE_TO)
.setCheck(Types.NUMBER.compatibleTypes);
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 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(
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 Types.NUMBER.typeId;
},
/**
* 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, 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 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": Types.BOOLEAN.compatibleTypes
}, {
"type": "field_dropdown",
"name": "PULSEPIN",
"options": selectedBoard().digitalPins,
}
],
"output": Types.NUMBER.typeId,
"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 Types.NUMBER.typeId;
}
};
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": Types.BOOLEAN.compatibleTypes
}, {
"type": "field_dropdown",
"name": "PULSEPIN",
"options": selectedBoard().digitalPins,
}, {
"type": "input_value",
"name": "TIMEOUT",
"check": Types.NUMBER.compatibleTypes
}
],
"output": Types.NUMBER.typeId,
"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 Types.NUMBER.typeId;
}
};

View File

@ -1,61 +1,235 @@
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"]
}
]);
]); // 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}"
}
]);

View File

@ -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'],
},

View File

@ -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;
}
};

View File

View File

@ -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;
}
};

View File

@ -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'],
};

View File

@ -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'],
};

View File

@ -0,0 +1,112 @@
import * as Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
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) {
//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'],
};

View File

@ -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,299 @@ 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;
},
};
};
/**
* 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) {
(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) {
(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;
default:
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;
},
};

View File

@ -0,0 +1,53 @@
import Blockly from 'blockly';
import { getColour } from '../helpers/colour'
Blockly.Blocks["sensebox_telegram"] = {
init: function () {
this.setColour(getColour().sensebox);
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);
}
};
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"]
};

View File

@ -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);
}
};

View File

@ -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);
}
};

View File

@ -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);
}
};

View File

@ -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.
@ -81,6 +80,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 +101,20 @@ 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 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)
// 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 +195,47 @@ Blockly['Arduino'].init = function (workspace) {
*/
Blockly['Arduino'].finish = function (code) {
let libraryCode = '';
let variablesCode = '';
let codeFunctions = '';
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'].codeFunctions_) {
codeFunctions += Blockly['Arduino'].codeFunctions_[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 +244,12 @@ Blockly['Arduino'].finish = function (code) {
'\n' +
libraryCode +
'\n' +
variablesCode +
'\n' +
definitionsCode +
'\n' +
codeFunctions +
'\n' +
Blockly['Arduino'].variablesInitCode_ +
'\n' +
functionsCode +
@ -225,6 +262,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();

View File

@ -1,5 +1,16 @@
import './generator';
import './loops';
import './sensebox';
import './sensebox-sensors';
import './sensebox-telegram';
import './sensebox-osem';
import './sensebox-web';
import './sensebox-display';
import './sensebox-lora';
import './logic';
import './math';
import './map';
import './io';
import './procedures';
import './time';

View File

@ -0,0 +1,114 @@
import * as Blockly from 'blockly/core';
/**
* 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];
};
/**
* 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];
};

View File

@ -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.
@ -55,7 +54,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 = '',

View File

@ -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.');
};

View File

@ -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];
};

View File

@ -0,0 +1,347 @@
import * as Blockly from 'blockly/core';
/**
* @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;
default:
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 new Error('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 <math.h>');
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 <math.h>');
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;
default:
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];
};

View File

@ -0,0 +1,30 @@
import * as Blockly from 'blockly/core';
/**
* 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 new Error('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;
};

View File

@ -0,0 +1,92 @@
import * as Blockly from 'blockly/core';
/*Display Blocks*/
Blockly.Arduino.sensebox_display_beginDisplay = function () {
Blockly.Arduino.libraries_['library_spi'] = '#include <SPI.h>';
Blockly.Arduino.libraries_['library_wire'] = '#include <Wire.h>';
Blockly.Arduino.libraries_['library_AdafruitGFX'] = '#include <Adafruit_GFX.h>';
Blockly.Arduino.libraries_['library_AdafruitSSD1306'] = '#include <Adafruit_SSD1306.h>';
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 <Plot.h>';
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 () {
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') {
code = 'display.fillCircle(' + x + ',' + y + ',' + radius + ',1);\n';
}
else {
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') {
code = 'display.fillRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n';
}
else {
code = 'display.drawRect(' + x + ',' + y + ',' + width + ',' + height + ',1);\n';
}
return code;
}

View File

@ -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 <SPI.h>';
Blockly.Arduino.libraries_['library_lmic'] = '#include <lmic.h>';
Blockly.Arduino.libraries_['library_hal'] = '#include <hal/hal.h>';
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 <LoraMessage.h>';
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 <CayenneLPP.h>';
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 <SPI.h>';
Blockly.Arduino.libraries_['library_lmic'] = '#include <lmic.h>';
Blockly.Arduino.libraries_['library_hal'] = '#include <hal/hal.h>';
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;
}

View File

@ -0,0 +1,176 @@
import Blockly 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;
}
}
}`
code = '';
code += branch;
code += 'submitValues(' + lat + ',' + lng + ',' + altitude + ',' + timestamp + ');\n';
}
return code;
};

View File

@ -1,6 +1,228 @@
import * as Blockly from 'blockly/core';
import { Block } from 'blockly';
import Blockly from 'blockly';
Blockly.Arduino['sensebox_telegram'] = function (Block) {
/**
* HDC1080 Temperature and Humidity Sensor
*
*/
};
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');
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();'
code = 'veml.get' + dropdown_name + '()';
}
if (dropdown_name === 'Illuminance') {
Blockly.Arduino.definitions_['define_tsl'] = 'TSL45315 tsl;'
Blockly.Arduino.setupCode_['sensebox_sensor_illuminance'] = 'tsl.begin();'
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 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') {
code = 'bmp_sensor.get' + dropdown_name + '()';
}
else if (dropdown_name === 'Altitude') {
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');
let code = '';
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':
code = 'bmeTemperatur';
break;
case 'humidity':
code = 'bmeHumidity';
break;
case 'pressure':
code = 'bmePressure'
break;
case 'IAQ':
code = 'bmeIAQ';
break;
case 'IAQAccuracy':
code = 'bmeIAQAccuracy';
break;
case 'CO2':
code = 'bmeCO2';
break;
case 'breathVocEquivalent':
code = 'bmeBreathVocEquivalent';
break;
default:
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];
};

View File

@ -0,0 +1,57 @@
import * as Blockly from 'blockly/core';
/**
* 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 <UniversalTelegramBot.h>`
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<numNewMessages; i++) {
String chat_id = String(bot.messages[i].chat_id);
String text = bot.messages[i].text;
${messageProcessing}
}
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
Bot_lasttime = millis();
}`;
var code = '';
return code;
};
Blockly.Arduino.sensebox_telegram_do_on_message = function (block) {
var message = this.getFieldValue('telegram_message');
var stuffToDo = Blockly.Arduino.statementToCode(block, 'telegram_do_on_message', Blockly.Arduino.ORDER_ATOMIC);
var code = `
if (text == "${message}") {
${stuffToDo}
}`;
return code;
};
Blockly.Arduino.sensebox_telegram_send = function (block) {
var textToSend = Blockly.Arduino.valueToCode(this, 'telegram_text_to_send', Blockly.Arduino.ORDER_ATOMIC) || '"Keine Eingabe"';
var code = `bot.sendMessage(chat_id, String(${textToSend}), "");\n`;
return code;
};

View File

@ -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;
};

View File

@ -1,19 +1,3 @@
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 <UniversalTelegramBot.h>`
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;
};

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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<Blockly.Type>} 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<Array<string>>} 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;
// };

View File

@ -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:";

View File

@ -0,0 +1,297 @@
import React from 'react';
import { Block, Value, Field, Shadow, Category } from '../';
import { getColour } from '../helpers/colour'
class Toolbox extends React.Component {
render() {
return (
<xml xmlns="https://developers.google.com/blockly/xml" id="blockly" style={{ display: 'none' }} ref={this.props.toolbox}>
<Category name="senseBox" colour={getColour().sensebox}>
<Category name="Sensoren" colour={getColour().sensebox}>
<Block type="sensebox_sensor_temp_hum" />
<Block type="sensebox_sensor_uv_light" />
<Block type="sensebox_sensor_bmx055_accelerometer" />
<Block type="sensebox_sensor_sds011" />
<Block type="sensebox_sensor_pressure" />
<Block type="sensebox_sensor_bme680_bsec" />
<Block type="sensebox_sensor_ultrasonic_ranger" />
<Block type="sensebox_sensor_sound" />
</Category >
<Category name="WIFI" colour={getColour().sensebox}>
<Block type="sensebox_wifi" />
<Block type="sensebox_startap" />
</Category>
<Category name="Display" colour={getColour().sensebox}>
<Block type="sensebox_display_beginDisplay" />
<Block type="sensebox_display_show" />
<Block type="sensebox_display_clearDisplay" />
<Block type="sensebox_display_printDisplay">
<Value name="SIZE">
<Block type="math_number">
<Field name="NUM">1</Field>
</Block>
</Value>
<Value name="X">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="Y">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
</Block>
<Block type="sensebox_display_plotDisplay">
<Value name="Title">
<Block type="text">
</Block>
</Value>
<Value name="YLabel">
<Block type="text">
</Block>
</Value>
<Value name="XLabel">
<Block type="text">
</Block>
</Value>
<Value name="XRange1">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="XRange2">
<Block type="math_number">
<Field name="NUM">15</Field>
</Block>
</Value>
<Value name="YRange1">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="YRange2">
<Block type="math_number">
<Field name="NUM">50</Field>
</Block>
</Value>
<Value name="XTick">
<Block type="math_number">
<Field name="NUM">5</Field>
</Block>
</Value>
<Value name="YTick">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="TimeFrame">
<Block type="math_number">
<Field name="NUM">15</Field>
</Block>
</Value>
</Block>
<Block type="sensebox_display_fillCircle">
<Value name="X">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="Y">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="Radius">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
</Block>
<Block type="sensebox_display_drawRectangle">
<Value name="X">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="Y">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="height">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
<Value name="width">
<Block type="math_number">
<Field name="NUM">0</Field>
</Block>
</Value>
</Block>
</Category>
<Category name="Telegram" colour={getColour().sensebox}>
<Block type="sensebox_telegram" />
<Block type="sensebox_telegram_do" />
<Block type="sensebox_telegram_do_on_message" />
<Block type="sensebox_telegram_send" />
</Category>
<Category name="osem" colour={getColour().sensebox}>
<Block type="sensebox_osem_connection" />
</Category>
<Category id="catSenseBoxOutput_LoRa" name=" LoRa" colour={getColour().sensebox}>
<Category id="catSenseBoxOutput_LoRa_activation" name=" Activation" colour={getColour().sensebox}>
<Block type="sensebox_lora_initialize_otaa" />
<Block type="sensebox_lora_initialize_abp" />
</Category>
<Category id="catSenseBoxOutput_LoRa_loramessage" name=" Lora Message" colour={getColour().sensebox}>
<Block type="sensebox_lora_message_send" />
<Block type="sensebox_send_lora_sensor_value" />
</Category>
<Category id="catSenseBoxOutput_LoRa_cayenne" name=" Cayenne LPP" colour={getColour().sensebox}>
<Block type="sensebox_lora_cayenne_send" />
<Block type="sensebox_lora_cayenne_temperature" />
<Block type="sensebox_lora_cayenne_humidity" />
<Block type="sensebox_lora_cayenne_pressure" />
<Block type="sensebox_lora_cayenne_luminosity" />
<Block type="sensebox_lora_cayenne_sensor" />
<Block type="sensebox_lora_cayenne_accelerometer" />
<Block type="sensebox_lora_cayenne_gps" />
</Category>
</Category>
</Category>
<Category name="Logic" colour={getColour().logic}>
<Block type="controls_if" />
<Block type="controls_ifelse" />
<Block type="logic_compare" />
<Block type="logic_operation" />
<Block type="logic_negate" />
<Block type="logic_boolean" />
</Category>
<Category id="loops" name="Loops" colour={getColour().loops}>
<Block type="controls_repeat_ext">
<Value name="TIMES">
<Block type="math_number">
<Field name="NUM">10</Field>
</Block>
</Value>
</Block>
<Block type="controls_whileUntil" />
<Block type="controls_for">
<Value name="FROM">
<Block type="math_number">
<Field name="NUM">1</Field>
</Block>
</Value>
<Value name="TO" >
<Block type="math_number" >
<Field name="NUM">10</Field>
</Block>
</Value>
<Value name="BY" >
<Block Type="math_number" >
<Field name="NUM">1</Field>
</Block>
</Value>
</Block>
<Block type="controls_flow_statements" />
</Category>
<Category id="time" name="Time" colour={getColour().time}>
<Block type="time_delay">
<Value name="DELAY_TIME_MILI">
<Block type="math_number">
<Field name="NUM">1000</Field>
</Block>
</Value>
</Block>
<Block type="time_delaymicros">
<Value name="DELAY_TIME_MICRO">
<Block type="math_number">
<Field name="NUM">100</Field>
</Block>
</Value>
</Block>
<Block type="time_millis"></Block>
<Block type="time_micros"></Block>
<Block type="infinite_loop"></Block>
<Block type="sensebox_interval_timer"></Block>
</Category>
<Category id="catMath" name="Math" colour={getColour().math}>
<Block type="math_number"></Block>
<Block type="math_arithmetic"></Block>
<Block type="math_single"></Block>
<Block type="math_trig"></Block>
<Block type="math_constant"></Block>
<Block type="math_number_property"></Block>
<Block type="math_change">
<Value name="DELTA">
<Block type="math_number">
<Field name="NUM">1</Field>
</Block>
</Value>
</Block>
<Block type="math_round"></Block>
<Block type="math_modulo"></Block>
<Block type="math_constrain">
<Value name="LOW">
<Block type="math_number">
<Field name="NUM">1</Field>
</Block>
</Value>
<Value name="HIGH">
<Block type="math_number">
<Field name="NUM">100</Field>
</Block>
</Value>
</Block>
<Block type="math_random_int">
<Value name="FROM">
<Block type="math_number">
<Field name="NUM">1</Field>
</Block>
</Value>
<Value name="TO">
<Block type="math_number">
<Field name="NUM">100</Field>
</Block>
</Value>
</Block>
<Block type="math_random_float"></Block>
<Block type="base_map"></Block>
</Category>
<sep></sep>
<Category name="Input/Output" colour={getColour().io}>
<Block type="io_digitalwrite"></Block>
<Block type="io_digitalread"></Block>
<Block type="io_builtin_led"></Block>
<Block type="io_analogwrite"></Block>
<Block type="io_analogread"></Block>
<Block type="io_highlow"></Block>
<Block type="io_pulsein">
<Value name="PULSETYPE">
<Shadow type="io_highlow"></Shadow>
</Value>
</Block>
<Block type="io_pulsetimeout">
<Value name="PULSETYPE">
<Shadow type="io_highlow"></Shadow>
</Value>
<Value name="TIMEOUT">
<Shadow type="math_number">
<Field name="NUM">100</Field>
</Shadow>
</Value>
</Block>
</Category>
<Category name="Procedures" colour={getColour().procedures}>
<Block type="arduino_functions" />
</Category>
</xml>
);
};
}
export default Toolbox;

View File

@ -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 (
<div style={{height: '500px'}}>
<Card style={{height: '500px'}}>
<Accordion
square={true}
style={{margin: 0}}
@ -110,7 +112,7 @@ class CodeViewer extends Component {
</pre>
</AccordionDetails>
</Accordion>
</div>
</Card>
);
};
}

View File

@ -11,13 +11,14 @@ 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 = {
codeOn: false
}
componentDidUpdate(){
componentDidUpdate() {
/* Resize and reposition all of the workspace chrome (toolbox, trash,
scrollbars etc.) This should be called when something changes that requires
recalculating dimensions and positions of the trash, zoom, toolbox, etc.
@ -35,19 +36,19 @@ class Home extends Component {
<div>
<WorkspaceStats />
<Grid container spacing={2}>
<Grid item xs={12} md={this.state.codeOn ? 6 : 12} style={{position: 'relative'}}>
<Grid item xs={12} md={this.state.codeOn ? 6 : 12} style={{ position: 'relative' }}>
<FormControlLabel
style={{margin: '5px 10px 0 0', position: 'absolute', top: 0, right:0, zIndex:1}}
control={<Switch checked={this.state.codeOn} onChange={this.onChange} color='primary'/>}
style={{ margin: '5px 10px 0 0', position: 'absolute', top: 0, right: 0, zIndex: 1 }}
control={<Switch checked={this.state.codeOn} onChange={this.onChange} color='primary' />}
label="Code"
/>
<BlocklyWindow />
</Grid>
{this.state.codeOn ?
<Grid item xs={12} md={6}>
<CodeViewer/>
<CodeViewer />
</Grid>
: null}
: null}
</Grid>
<WorkspaceFunc />
</div>

View File

@ -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 (
<div style={{ marginTop: '20px' }}>
@ -51,6 +74,9 @@ class WorkspaceFunc extends Component {
Get XML Code
</Button>
<MaxBlocks />
<Button style={{ float: 'right', color: 'white' }} variant="contained" color="primary" onClick={() => this.compile()}>
Compile
</Button>
</div>
);
};

View File

@ -1,4 +1,4 @@
import React, {Component} from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
@ -6,7 +6,8 @@ import * as Blockly from 'blockly/core';
import { withStyles } from '@material-ui/core/styles';
import Tooltip from '@material-ui/core/Tooltip';
import Typography from '@material-ui/core/Typography';
import Chip from '@material-ui/core/Chip';
import Avatar from '@material-ui/core/Avatar';
import { faPuzzlePiece, faTrash, faPlus, faPen, faArrowsAlt } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
@ -17,7 +18,7 @@ const styles = (theme) => ({
display: 'inline',
marginLeft: '50px',
padding: '3px 10px',
borderRadius: '25%'
// borderRadius: '25%'
}
});
@ -27,44 +28,54 @@ class WorkspaceStats extends Component {
const workspace = Blockly.getMainWorkspace();
const remainingBlocksInfinity = workspace ? workspace.remainingCapacity() !== Infinity : null;
return (
<div style={{marginBottom: '20px', color: 'white'}}>
<Tooltip title="Anzahl aktueller Blöcke" style={{marginLeft: 0}} className={this.props.classes.stats}>
<div>
<FontAwesomeIcon icon={faPuzzlePiece} />
<Typography style={{display: 'inline'}}> {workspace ? workspace.getAllBlocks().length : 0}</Typography>
</div>
<div style={{ marginBottom: '20px' }}>
<Tooltip title="Anzahl aktueller Blöcke" >
<Chip
style={{ marginRight: '1rem' }}
color="primary"
avatar={<Avatar><FontAwesomeIcon icon={faPuzzlePiece} /></Avatar>}
label={workspace ? workspace.getAllBlocks().length : 0}>
</Chip>
</Tooltip>
<Tooltip title="Anzahl neuer Blöcke" className={this.props.classes.stats}>
<div>
<FontAwesomeIcon icon={faPlus} style={{marginRight: '5px'}}/>
<FontAwesomeIcon icon={faPuzzlePiece} />
<Typography style={{display: 'inline'}}> {this.props.create}</Typography>
</div>
<Tooltip title="Anzahl neuer Blöcke" >
<Chip
style={{ marginRight: '1rem' }}
color="primary"
avatar={<Avatar><FontAwesomeIcon icon={faPlus} /></Avatar>}
label={this.props.create}>
</Chip>
</Tooltip>
<Tooltip title="Anzahl veränderter Blöcke" className={this.props.classes.stats}>
<div>
<FontAwesomeIcon icon={faPen} style={{marginRight: '5px'}}/>
<FontAwesomeIcon icon={faPuzzlePiece} />
<Typography style={{display: 'inline'}}> {this.props.change}</Typography>
</div>
<Tooltip title="Anzahl veränderter Blöcke" >
<Chip
style={{ marginRight: '1rem' }}
color="primary"
avatar={<Avatar><FontAwesomeIcon icon={faPen} /></Avatar>}
label={this.props.change}>
</Chip>
</Tooltip>
<Tooltip title="Anzahl bewegter Blöcke" className={this.props.classes.stats}>
<div>
<FontAwesomeIcon icon={faArrowsAlt} style={{marginRight: '5px'}}/>
<FontAwesomeIcon icon={faPuzzlePiece} />
<Typography style={{display: 'inline'}}> {this.props.move}</Typography>
</div>
<Tooltip title="Anzahl bewegter Blöcke" >
<Chip
style={{ marginRight: '1rem' }}
color="primary"
avatar={<Avatar><FontAwesomeIcon icon={faArrowsAlt} /></Avatar>}
label={this.props.move}>
</Chip>
</Tooltip>
<Tooltip title="Anzahl gelöschter Blöcke" className={this.props.classes.stats}>
<div>
<FontAwesomeIcon icon={faTrash} style={{marginRight: '5px'}}/>
<FontAwesomeIcon icon={faPuzzlePiece} />
<Typography style={{display: 'inline'}}> {this.props.delete}</Typography>
</div>
<Tooltip title="Anzahl gelöschter Blöcke" >
<Chip
style={{ marginRight: '1rem' }}
color="primary"
avatar={<Avatar><FontAwesomeIcon icon={faTrash} /></Avatar>}
label={this.props.delete}>
</Chip>
</Tooltip>
{remainingBlocksInfinity ?
<Tooltip title="verbleibende Blöcke" className={this.props.classes.stats}>
<Typography style={{display: 'inline'}}>{workspace.remainingCapacity()} verbleibende Blöcke</Typography>
<Tooltip title="Verbleibende Blöcke" >
<Chip
style={{ marginRight: '1rem' }}
color="primary"
label={workspace.remainingCapacity()}>
</Chip>
</Tooltip> : null}
</div>
);
@ -87,4 +98,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));

View File

@ -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__()
)
);