Merge pull request #7 from sensebox/typed-variables

Typed variables
This commit is contained in:
Mario Pesch 2020-09-29 12:21:58 +00:00 committed by GitHub
commit 67cc477d28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 12995 additions and 246 deletions

41
package-lock.json generated
View File

@ -1097,14 +1097,27 @@
}
},
"@blockly/block-plus-minus": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/@blockly/block-plus-minus/-/block-plus-minus-2.0.8.tgz",
"integrity": "sha512-LRn+Js2rZ14XyrSoEf7wTz6/ESNW2MI5TkXJ2wWFJVA+/E4lTfBwXeZpRFYRP9DZwNEv9alZETyEcBbK+FCZKw=="
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/@blockly/block-plus-minus/-/block-plus-minus-2.0.10.tgz",
"integrity": "sha512-YWEQd9xHAAn1aJgIuZsAdx2t9ZSjinaSEzbN1c43iU584TvaiPsGq5JcnLpoDIyGgJI90Nk+o4erWyQR+kqLyQ=="
},
"@blockly/field-slider": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@blockly/field-slider/-/field-slider-2.0.7.tgz",
"integrity": "sha512-kSFeeyfJboj2zOz55hgunFzRHQZUTWmKgw695GOwOGvt4wTG5SQ2/pNnd+C41vdjaOdjaI8tlwiyWg4oJ/MPeA=="
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@blockly/field-slider/-/field-slider-2.1.1.tgz",
"integrity": "sha512-VclXqKRs94iHl7yhFNCK+a1uyiHtPHgoAYXugr7hbZ6BZWGdI9tV1iMeiILz4pNlhy6llM+QvbJopjYA+4oCFQ=="
},
"@blockly/plugin-modal": {
"version": "1.20200427.4",
"resolved": "https://registry.npmjs.org/@blockly/plugin-modal/-/plugin-modal-1.20200427.4.tgz",
"integrity": "sha512-eA9p+W3mtcWLJQZ23D0Le/Uw3JdxFxwJqTUYtAiRlVON4qnuDXrHQLlvxEiWctNXJZGUTh57zqbvO6ZxNRQPrA=="
},
"@blockly/plugin-typed-variable-modal": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@blockly/plugin-typed-variable-modal/-/plugin-typed-variable-modal-3.1.1.tgz",
"integrity": "sha512-+g/lQ3HrCcivBNOtgvQEvfZCPq9VeP1Zgs7J02zxAfw4f+s4aOQb+hChv7qAb5AnzEnMk0BoB5vKgQmaP6Wkuw==",
"requires": {
"@blockly/plugin-modal": "^1.20200427.4"
}
},
"@cnakazawa/watch": {
"version": "1.0.4",
@ -3065,9 +3078,9 @@
}
},
"blockly": {
"version": "3.20200625.2",
"resolved": "https://registry.npmjs.org/blockly/-/blockly-3.20200625.2.tgz",
"integrity": "sha512-+0aUynP4kAFjg+m9uSyctWB+KwT3/BDmqy4Fm7vwWq7cuMtgIsqqA8VGb6INVpFx9WZUXSZ5enFAco6CM85bpA==",
"version": "3.20200924.0",
"resolved": "https://registry.npmjs.org/blockly/-/blockly-3.20200924.0.tgz",
"integrity": "sha512-mOZiXi908oNFAcVb8Q5LKJNRZ5jtBJtgNilddqTYMAXEdqSY/BhcnU2rgytWARDnu2iSQlI374kEafCNuUEWKQ==",
"requires": {
"jsdom": "^15.2.1"
},
@ -5947,6 +5960,11 @@
"schema-utils": "^2.5.0"
}
},
"file-saver": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz",
"integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw=="
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
@ -8702,6 +8720,11 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz",
"integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",

View File

@ -3,8 +3,9 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@blockly/block-plus-minus": "^2.0.8",
"@blockly/field-slider": "^2.0.7",
"@blockly/block-plus-minus": "^2.0.10",
"@blockly/field-slider": "^2.1.1",
"@blockly/plugin-typed-variable-modal": "^3.1.1",
"@fortawesome/fontawesome-svg-core": "^1.2.30",
"@fortawesome/free-solid-svg-icons": "^5.14.0",
"@fortawesome/react-fontawesome": "^0.1.11",
@ -12,7 +13,7 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"blockly": "^3.20200625.2",
"blockly": "^3.20200924.0",
"file-saver": "^2.0.2",
"moment": "^2.28.0",
"prismjs": "^1.20.0",

View File

@ -34,10 +34,12 @@ import { Card } from '@material-ui/core';
Blockly.setLocale(locale);
class BlocklyComponent extends React.Component {
constructor(props) {
super(props);
this.blocklyDiv = React.createRef();
this.toolbox = React.createRef();
this.state = {workspace: undefined};
}
componentDidMount() {
@ -49,6 +51,7 @@ class BlocklyComponent extends React.Component {
...rest
},
);
this.setState({workspace: this.primaryWorkspace})
if (initialXml) {
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(initialXml), this.primaryWorkspace);
@ -64,11 +67,9 @@ class BlocklyComponent extends React.Component {
}
render() {
return <React.Fragment>
<Card ref={this.blocklyDiv} id="blocklyDiv" style={this.props.style ? this.props.style : {}}/>
<Toolbox toolbox={this.toolbox} />
<Toolbox toolbox={this.toolbox} workspace={this.state.workspace} />
</React.Fragment>;
}
}

View File

@ -28,7 +28,7 @@ class BlocklyWindow extends Component {
this.props.onChangeWorkspace(event);
// switch on that a block is displayed disabled or not depending on whether it is correctly connected
// for SVG display, a deactivated block in the display is undesirable
if(this.props.blockDisabled){
if (this.props.blockDisabled) {
Blockly.Events.disableOrphans(event);
}
});
@ -39,10 +39,10 @@ class BlocklyWindow extends Component {
const workspace = Blockly.getMainWorkspace();
var xml = this.props.initialXml;
// if svg is true, then the update process is done in the BlocklySvg component
if(props.initialXml !== xml && !this.props.svg){
if (props.initialXml !== xml && !this.props.svg) {
// guarantees that the current xml-code (this.props.initialXml) is rendered
workspace.clear();
if(!xml) xml = initialXml;
if (!xml) xml = initialXml;
Blockly.Xml.domToWorkspace(Blockly.Xml.textToDom(xml), workspace);
}
Blockly.svgResize(workspace);
@ -52,7 +52,7 @@ class BlocklyWindow extends Component {
return (
<div>
<BlocklyComponent ref={this.simpleWorkspace}
style={this.props.svg ? {height: 0} : this.props.blocklyCSS}
style={this.props.svg ? { height: 0 } : this.props.blocklyCSS}
readOnly={this.props.readOnly !== undefined ? this.props.readOnly : false}
trashcan={this.props.trashcan !== undefined ? this.props.trashcan : true}
renderer='zelos'
@ -70,18 +70,18 @@ class BlocklyWindow extends Component {
length: 1,
colour: '#4EAF47', // senseBox-green
snap: false
}}
}}
media={'/media/blockly/'}
move={this.props.move !== undefined && !this.props.move ? {} :
{ // https://developers.google.com/blockly/guides/configure/web/move
scrollbars: true,
drag: true,
wheel: false
}}
}}
initialXml={this.props.initialXml ? this.props.initialXml : initialXml}
>
</BlocklyComponent >
{this.props.svg && this.props.initialXml ? <BlocklySvg initialXml={this.props.initialXml}/> : null}
{this.props.svg && this.props.initialXml ? <BlocklySvg initialXml={this.props.initialXml} /> : null}
</div>
);
};

View File

@ -0,0 +1,61 @@
import Blockly from 'blockly/core';
import { selectedBoard } from '../helpers/board'
import * as Types from '../helpers/types'
import { getColour } from '../helpers/colour';
Blockly.Blocks['io_tone'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.ARD_SETTONE)
.appendField(new Blockly.FieldDropdown(
selectedBoard().digitalPins), "TONEPIN");
this.appendValueInput("FREQUENCY")
.setCheck(Types.getCompatibleTypes('int'))
.appendField(Blockly.Msg.ARD_TONEFREQ);
this.appendDummyInput()
.appendField("Hz");
this.setInputsInline(true);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setColour(getColour().audio);
this.setTooltip(Blockly.Msg.ARD_TONE_TIP);
this.setHelpUrl('https://www.arduino.cc/en/Reference/tone');
},
/**
* Called whenever anything on the workspace changes.
* It checks frequency values and sets a warning if out of range.
* @this Blockly.Block
*/
onchange: function (event) {
if (!this.workspace || event.type === Blockly.Events.MOVE ||
event.type === Blockly.Events.UI) {
return; // Block deleted or irrelevant event
}
var freq = Blockly.Arduino.valueToCode(
this, "FREQUENCY", Blockly.Arduino.ORDER_ATOMIC)
if (freq < 31 || freq > 65535) {
this.setWarningText(Blockly.Msg.ARD_TONE_WARNING, 'io_tone');
} else {
this.setWarningText(null, 'io_tone');
}
}
};
Blockly.Blocks['io_notone'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.ARD_NOTONE)
.appendField(new Blockly.FieldDropdown(
selectedBoard().digitalPins), "TONEPIN");
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setColour(getColour().audio);
this.setTooltip(Blockly.Msg.ARD_NOTONE_TIP);
this.setHelpUrl('https://www.arduino.cc/en/Reference/noTone');
},
/** @return {!string} The type of input value for the block, an integer. */
getBlockType: function () {
return Blockly.Types.NUMBER;
}
};

View File

@ -8,11 +8,14 @@ import './sensebox-web';
import './sensebox-display';
import './sensebox-lora';
import './sensebox-led';
import './sensebox-sd';
import './text';
import './io';
import './audio';
import './math';
import './map';
import './procedures';
import './time';
import './variables';
import '../helpers/types'

View File

@ -56,7 +56,7 @@ Blockly.Blocks['io_digitalread'] = {
.appendField(Blockly.Msg.ARD_DIGITALREAD)
.appendField(new Blockly.FieldDropdown(
selectedBoard().digitalPins), 'PIN');
this.setOutput(true, Types.BOOLEAN);
this.setOutput(true, 'boolean');
this.setTooltip(Blockly.Msg.ARD_DIGITALREAD_TIP);
},
/** @return {!string} The type of return value for the block, an integer. */

View File

@ -1,6 +1,5 @@
import Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
Blockly.defineBlocksWithJsonArray([ // BEGIN JSON EXTRACT
@ -232,4 +231,169 @@ Blockly.defineBlocksWithJsonArray([ // Mutator blocks. Do not extract.
]);
Blockly.Blocks['switch_case'] = {
init: function () {
this.setColour(getColour().logic);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.appendValueInput('CONDITION')
.appendField(Blockly.Msg.cases_switch);
this.appendValueInput('CASECONDITION0')
.appendField(Blockly.Msg.cases_condition);
this.appendStatementInput('CASE0')
.appendField(Blockly.Msg.cases_do);
this.setMutator(new Blockly.Mutator(['case_incaseof', 'case_default']));
this.setTooltip('Does something if the condition is true. If there isn\'t a matching case the default function will be executed.');
this.caseCount_ = 0;
this.defaultCount_ = 0;
},
mutationToDom: function () {
if (!this.caseCount_ && !this.defaultCount_) {
return null;
}
var container = document.createElement('mutation');
if (this.caseCount_) {
container.setAttribute('case', this.caseCount_);
}
if (this.defaultCount_) {
container.setAttribute('default', 1);
}
return container;
},
domToMutation: function (xmlElement) {
this.caseCount_ = parseInt(xmlElement.getAttribute('case'), 10);
this.defaultCount_ = parseInt(xmlElement.getAttribute('default'), 10);
for (var x = 0; x <= this.caseCount_; x++) {
this.appendValueInput('CASECONDITION' + x)
.appendField(Blockly.Msg.cases_condition);
this.appendStatementInput('CASE' + x)
.appendField(Blockly.Msg.cases_do);
}
if (this.defaultCount_) {
this.appendStatementInput('ONDEFAULT')
.appendField('default');
}
},
decompose: function (workspace) {
var containerBlock = workspace.newBlock('control_case');
containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection;
for (var x = 1; x <= this.caseCount_; x++) {
var caseBlock = workspace.newBlock('case_incaseof');
caseBlock.initSvg();
connection.connect(caseBlock.previousConnection);
connection = caseBlock.nextConnection;
}
if (this.defaultCount_) {
var defaultBlock = Blockly.Block.obtain(workspace, 'case_default');
defaultBlock.initSvg();
connection.connect(defaultBlock.previousConnection);
}
return containerBlock;
},
compose: function (containerBlock) {
//Disconnect all input blocks and remove all inputs.
if (this.defaultCount_) {
this.removeInput('ONDEFAULT');
}
this.defaultCount_ = 0;
for (var x = this.caseCount_; x > 0; x--) {
this.removeInput('CASECONDITION' + x);
this.removeInput('CASE' + x);
}
this.caseCount_ = 0;
var caseBlock = containerBlock.getInputTargetBlock('STACK');
while (caseBlock) {
switch (caseBlock.type) {
case 'case_incaseof':
this.caseCount_++;
var caseconditionInput = this.appendValueInput('CASECONDITION' + this.caseCount_)
.appendField(Blockly.Msg.cases_condition);
var caseInput = this.appendStatementInput('CASE' + this.caseCount_)
.appendField(Blockly.Msg.cases_do);
if (caseBlock.valueConnection_) {
caseconditionInput.connection.connect(caseBlock.valueConnection_);
}
if (caseBlock.statementConnection_) {
caseInput.connection.connect(caseBlock.statementConnection_);
}
break;
case 'case_default':
this.defaultCount_++;
var defaultInput = this.appendStatementInput('ONDEFAULT')
.appendField('default');
if (caseBlock.statementConnection_) {
defaultInput.connection.connect(caseBlock.statementConnection_);
}
break;
default:
throw new Error('Unknown block type.');
}
caseBlock = caseBlock.nextConnection &&
caseBlock.nextConnection.targetBlock();
}
},
saveConnections: function (containerBlock) {
var caseBlock = containerBlock.getInputTargetBlock('STACK');
var x = 1;
while (caseBlock) {
switch (caseBlock.type) {
case 'case_incaseof':
var caseconditionInput = this.getInput('CASECONDITION' + x);
var caseInput = this.getInput('CASE' + x);
caseBlock.valueConnection_ = caseconditionInput && caseconditionInput.connection.targetConnection;
caseBlock.statementConnection_ = caseInput && caseInput.connection.targetConnection;
x++;
break;
case 'case_default':
var defaultInput = this.getInput('ONDEFAULT');
caseBlock.satementConnection_ = defaultInput && defaultInput.connection.targetConnection;
break;
default:
throw new Error('Unknown block type');
}
caseBlock = caseBlock.nextConnection &&
caseBlock.nextConnection.targetBlock();
}
}
};
Blockly.Blocks['control_case'] = {
init: function () {
this.setColour(getColour().logic);
this.appendDummyInput()
.appendField(Blockly.Msg.cases_switch);
this.appendStatementInput('STACK');
this.setTooltip('--Placeholder--');
this.contextMenu = false;
}
};
Blockly.Blocks['case_incaseof'] = {
init: function () {
this.setColour(getColour().logic);
this.appendDummyInput()
.appendField(Blockly.Msg.cases_add);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip('--Placeholder--');
this.contextMenu = false;
}
};
Blockly.Blocks['case_default'] = {
init: function () {
this.setColour(getColour().logic);
this.appendValueInput('default')
.appendField('default');
this.setPreviousStatement(true);
this.setNextStatement(false);
this.setTooltip('This function will run if there aren\'t any matching cases.');
this.contextMenu = false;
}
};

View File

@ -0,0 +1,528 @@
import * as Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
import * as Types from '../helpers/types'
Blockly.Blocks['math_number'] = {
/**
* Block for numeric value.
* @this Blockly.Block
*/
init: function () {
this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);
this.setColour(getColour().math);
this.appendDummyInput()
.appendField(
new Blockly.FieldTextInput(
'0', Blockly.FieldTextInput.numberValidator),
'NUM');
this.setOutput(true, Types.NUMBER.typeName);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
// Number block is trivial. Use tooltip of parent block if it exists.
this.setTooltip(function () {
var parent = thisBlock.getParent();
return (parent && parent.getInputsInline() && parent.tooltip) ||
Blockly.Msg.MATH_NUMBER_TOOLTIP;
});
}
};
Blockly.Blocks['math_arithmetic'] = {
/**
* Block for basic arithmetic operator.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": "%1 %2 %3",
"args0": [
{
"type": "input_value",
"name": "A",
"check": Types.getCompatibleTypes('int')
},
{
"type": "field_dropdown",
"name": "OP",
"options":
[[Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'],
[Blockly.Msg.MATH_SUBTRACTION_SYMBOL, 'MINUS'],
[Blockly.Msg.MATH_MULTIPLICATION_SYMBOL, 'MULTIPLY'],
[Blockly.Msg.MATH_DIVISION_SYMBOL, 'DIVIDE'],
[Blockly.Msg.MATH_POWER_SYMBOL, 'POWER']]
},
{
"type": "input_value",
"name": "B",
"check": Types.getCompatibleTypes('int')
}
],
"inputsInline": true,
"output": Types.NUMBER.typeName,
"colour": getColour().math,
"helpUrl": Blockly.Msg.MATH_ARITHMETIC_HELPURL
});
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function () {
var mode = thisBlock.getFieldValue('OP');
var TOOLTIPS = {
'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,
'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,
'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,
'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,
'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER
};
return TOOLTIPS[mode];
});
}
//TODO: a getBlockType based on the two input types following C++ rules
};
Blockly.Blocks['math_single'] = {
/**
* Block for advanced math operators with single operand.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": "%1 %2",
"args0": [
{
"type": "field_dropdown",
"name": "OP",
"options": [
[Blockly.Msg.MATH_SINGLE_OP_ROOT, 'ROOT'],
[Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE, 'ABS'],
['-', 'NEG'],
['ln', 'LN'],
['log10', 'LOG10'],
['e^', 'EXP'],
['10^', 'POW10']
]
},
{
"type": "input_value",
"name": "NUM",
"check": Types.getCompatibleTypes('float')
}
],
"output": Types.DECIMAL.typeName,
"colour": getColour().math,
"helpUrl": Blockly.Msg.MATH_SINGLE_HELPURL
});
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function () {
var mode = thisBlock.getFieldValue('OP');
var TOOLTIPS = {
'ROOT': Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT,
'ABS': Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS,
'NEG': Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG,
'LN': Blockly.Msg.MATH_SINGLE_TOOLTIP_LN,
'LOG10': Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10,
'EXP': Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP,
'POW10': Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10
};
return TOOLTIPS[mode];
});
}
};
Blockly.Blocks['math_trig'] = {
/**
* Block for trigonometry operators.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": "%1 %2",
"args0": [
{
"type": "field_dropdown",
"name": "OP",
"options": [
[Blockly.Msg.MATH_TRIG_SIN, 'SIN'],
[Blockly.Msg.MATH_TRIG_COS, 'COS'],
[Blockly.Msg.MATH_TRIG_TAN, 'TAN'],
[Blockly.Msg.MATH_TRIG_ASIN, 'ASIN'],
[Blockly.Msg.MATH_TRIG_ACOS, 'ACOS'],
[Blockly.Msg.MATH_TRIG_ATAN, 'ATAN']
]
},
{
"type": "input_value",
"name": "NUM",
"check": Types.getCompatibleTypes('float')
}
],
"output": Types.DECIMAL.typeName,
"colour": getColour().math,
"helpUrl": Blockly.Msg.MATH_TRIG_HELPURL
});
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function () {
var mode = thisBlock.getFieldValue('OP');
var TOOLTIPS = {
'SIN': Blockly.Msg.MATH_TRIG_TOOLTIP_SIN,
'COS': Blockly.Msg.MATH_TRIG_TOOLTIP_COS,
'TAN': Blockly.Msg.MATH_TRIG_TOOLTIP_TAN,
'ASIN': Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN,
'ACOS': Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS,
'ATAN': Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN
};
return TOOLTIPS[mode];
});
}
};
Blockly.Blocks['math_constant'] = {
/**
* Block for constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": "%1",
"args0": [
{
"type": "field_dropdown",
"name": "CONSTANT",
"options": [
['\u03c0', 'PI'],
['e', 'E'],
['\u03c6', 'GOLDEN_RATIO'],
['sqrt(2)', 'SQRT2'],
['sqrt(\u00bd)', 'SQRT1_2'],
['\u221e', 'INFINITY']
]
}
],
"output": Types.DECIMAL.typeName,
"colour": getColour().math,
"tooltip": Blockly.Msg.MATH_CONSTANT_TOOLTIP,
"helpUrl": Blockly.Msg.MATH_CONSTANT_HELPURL
});
}
};
Blockly.Blocks['math_number_property'] = {
/**
* Block for checking if a number is even, odd, prime, whole, positive,
* negative or if it is divisible by certain number.
* @this Blockly.Block
*/
init: function () {
var PROPERTIES =
[[Blockly.Msg.MATH_IS_EVEN, 'EVEN'],
[Blockly.Msg.MATH_IS_ODD, 'ODD'],
[Blockly.Msg.MATH_IS_PRIME, 'PRIME'],
[Blockly.Msg.MATH_IS_WHOLE, 'WHOLE'],
[Blockly.Msg.MATH_IS_POSITIVE, 'POSITIVE'],
[Blockly.Msg.MATH_IS_NEGATIVE, 'NEGATIVE'],
[Blockly.Msg.MATH_IS_DIVISIBLE_BY, 'DIVISIBLE_BY']];
this.setColour(getColour().math);
this.appendValueInput('NUMBER_TO_CHECK')
.setCheck(Types.getCompatibleTypes('int'));
var dropdown = new Blockly.FieldDropdown(PROPERTIES, function (option) {
var divisorInput = (option === 'DIVISIBLE_BY');
this.sourceBlock_.updateShape_(divisorInput);
});
this.appendDummyInput()
.appendField(dropdown, 'PROPERTY');
this.setInputsInline(true);
this.setOutput(true, Types.BOOLEAN.typeName);
this.setTooltip(Blockly.Msg.MATH_IS_TOOLTIP);
},
/**
* Create XML to represent whether the 'divisorInput' should be present.
* @return {Element} XML storage element.
* @this Blockly.Block
*/
mutationToDom: function () {
var container = document.createElement('mutation');
var divisorInput = (this.getFieldValue('PROPERTY') === 'DIVISIBLE_BY');
container.setAttribute('divisor_input', divisorInput);
return container;
},
/**
* Parse XML to restore the 'divisorInput'.
* @param {!Element} xmlElement XML storage element.
* @this Blockly.Block
*/
domToMutation: function (xmlElement) {
var divisorInput = (xmlElement.getAttribute('divisor_input') === 'true');
this.updateShape_(divisorInput);
},
/**
* Modify this block to have (or not have) an input for 'is divisible by'.
* @param {boolean} divisorInput True if this block has a divisor input.
* @private
* @this Blockly.Block
*/
updateShape_: function (divisorInput) {
// Add or remove a Value Input.
var inputExists = this.getInput('DIVISOR');
if (divisorInput) {
if (!inputExists) {
this.appendValueInput('DIVISOR')
.setCheck(Types.getCompatibleTypes('int'));
}
} else if (inputExists) {
this.removeInput('DIVISOR');
}
}
};
Blockly.Blocks['math_change'] = {
/**
* Block for adding to a variable in place.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": Blockly.Msg.MATH_CHANGE_TITLE,
"args0": [
{
"type": "field_variable",
"name": "VAR",
"variable": Blockly.Msg.MATH_CHANGE_TITLE_ITEM
},
{
"type": "input_value",
"name": "DELTA",
"check": Types.getCompatibleTypes('int'),
"align": "RIGHT"
}
],
"previousStatement": null,
"nextStatement": null,
"colour": getColour().math,
"helpUrl": Blockly.Msg.MATH_CHANGE_HELPURL
});
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function () {
return Blockly.Msg.MATH_CHANGE_TOOLTIP.replace('%1',
thisBlock.getFieldValue('VAR'));
});
}
};
Blockly.Blocks['math_round'] = {
/**
* Block for rounding functions.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": "%1 %2",
"args0": [
{
"type": "field_dropdown",
"name": "OP",
"options": [
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUND, 'ROUND'],
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP, 'ROUNDUP'],
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN, 'ROUNDDOWN']
]
},
{
"type": "input_value",
"name": "NUM",
"check": Types.getCompatibleTypes('float')
}
],
"output": Types.DECIMAL.typeName,
"colour": getColour().math,
"tooltip": Blockly.Msg.MATH_ROUND_TOOLTIP,
"helpUrl": Blockly.Msg.MATH_ROUND_HELPURL
});
}
};
Blockly.Blocks['math_on_list'] = {
/**
* Block for evaluating a list of numbers to return sum, average, min, max,
* etc. Some functions also work on text (min, max, mode, median).
* @this Blockly.Block
*/
init: function () {
var OPERATORS =
[[Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MIN, 'MIN'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MAX, 'MAX'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE, 'AVERAGE'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN, 'MEDIAN'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MODE, 'MODE'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV, 'STD_DEV'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM, 'RANDOM']];
// Assign 'this' to a variable for use in the closures below.
var thisBlock = this;
this.setHelpUrl(Blockly.Msg.MATH_ONLIST_HELPURL);
this.setColour(getColour().math);
this.setOutput(true, Types.NUMBER.typeName);
var dropdown = new Blockly.FieldDropdown(OPERATORS, function (newOp) {
thisBlock.updateType_(newOp);
});
this.appendValueInput('LIST')
.setCheck(Types.getCompatibleTypes('array'))
.appendField(dropdown, 'OP');
this.setTooltip(function () {
var mode = thisBlock.getFieldValue('OP');
var TOOLTIPS = {
'SUM': Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM,
'MIN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN,
'MAX': Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX,
'AVERAGE': Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE,
'MEDIAN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN,
'MODE': Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE,
'STD_DEV': Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV,
'RANDOM': Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM
};
return TOOLTIPS[mode];
});
},
/**
* Modify this block to have the correct output type.
* @param {string} newOp Either 'MODE' or some op than returns a number.
* @private
* @this Blockly.Block
*/
updateType_: function (newOp) {
if (newOp === 'MODE') {
this.outputConnection.setCheck(Types.getCompatibleTypes('array'));
} else {
this.outputConnection.setCheck(Types.getCompatibleTypes('int'));
}
},
/**
* Create XML to represent the output type.
* @return {Element} XML storage element.
* @this Blockly.Block
*/
mutationToDom: function () {
var container = document.createElement('mutation');
container.setAttribute('op', this.getFieldValue('OP'));
return container;
},
/**
* Parse XML to restore the output type.
* @param {!Element} xmlElement XML storage element.
* @this Blockly.Block
*/
domToMutation: function (xmlElement) {
this.updateType_(xmlElement.getAttribute('op'));
}
//TODO: a getBlockType once the list code is finished.
};
Blockly.Blocks['math_modulo'] = {
/**
* Block for remainder of a division.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": Blockly.Msg.MATH_MODULO_TITLE,
"args0": [
{
"type": "input_value",
"name": "DIVIDEND",
"check": Types.getCompatibleTypes('int')
},
{
"type": "input_value",
"name": "DIVISOR",
"check": Types.getCompatibleTypes('int')
}
],
"inputsInline": true,
"output": Types.NUMBER.typeName,
"colour": getColour().math,
"tooltip": Blockly.Msg.MATH_MODULO_TOOLTIP,
"helpUrl": Blockly.Msg.MATH_MODULO_HELPURL
});
}
};
Blockly.Blocks['math_constrain'] = {
/**
* Block for constraining a number between two limits.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": Blockly.Msg.MATH_CONSTRAIN_TITLE,
"args0": [
{
"type": "input_value",
"name": "VALUE",
"check": Types.getCompatibleTypes('int')
},
{
"type": "input_value",
"name": "LOW",
"check": Types.getCompatibleTypes('int')
},
{
"type": "input_value",
"name": "HIGH",
"check": Types.getCompatibleTypes('int')
}
],
"inputsInline": true,
"output": Types.NUMBER.typeName,
"colour": getColour().math,
"tooltip": Blockly.Msg.MATH_CONSTRAIN_TOOLTIP,
"helpUrl": Blockly.Msg.MATH_CONSTRAIN_HELPURL
});
}
//TODO: a getBlockType of the same type as the inputs.
};
Blockly.Blocks['math_random_int'] = {
/**
* Block for random integer between [X] and [Y].
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": Blockly.Msg.MATH_RANDOM_INT_TITLE,
"args0": [
{
"type": "input_value",
"name": "FROM",
"check": Types.getCompatibleTypes('int')
},
{
"type": "input_value",
"name": "TO",
"check": Types.getCompatibleTypes('int')
}
],
"inputsInline": true,
"output": Types.NUMBER.typeName,
"colour": getColour().math,
"tooltip": Blockly.Msg.MATH_RANDOM_INT_TOOLTIP,
"helpUrl": Blockly.Msg.MATH_RANDOM_INT_HELPURL
});
}
};
Blockly.Blocks['math_random_float'] = {
/**
* Block for random fraction between 0 and 1.
* @this Blockly.Block
*/
init: function () {
this.jsonInit({
"message0": Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM,
"output": Types.DECIMAL.typeName,
"colour": getColour().math,
"tooltip": Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP,
"helpUrl": Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL
});
}
};

View File

@ -50,6 +50,8 @@ Blockly.Blocks['sensebox_display_printDisplay'] = {
.setCheck(null);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
let variableName = this.getField('COLOR');
console.log(variableName.getValue());
this.setTooltip(Blockly.Msg.senseBox_display_printDisplay_tip);
this.setHelpUrl('https://sensebox.de/books');
},

View File

@ -0,0 +1,80 @@
import * as Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
Blockly.Blocks['sensebox_sd_open_file'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_sd_open_file)
.setAlign(Blockly.ALIGN_LEFT)
.appendField(
new Blockly.FieldTextInput('Data.txt'),
'Filename');
this.appendStatementInput('SD')
.setCheck(null);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(getColour().sensebox);
this.setTooltip(Blockly.Msg.senseBox_output_safetosd_tip);
this.setHelpUrl('https://sensebox.de/books');
}
};
Blockly.Blocks['sensebox_sd_create_file'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_sd_create_file)
.setAlign(Blockly.ALIGN_LEFT)
.appendField(Blockly.Msg.senseBox_output_filename)
.appendField(
new Blockly.FieldTextInput('Data.txt'),
'Filename');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(getColour().sensebox);
this.setTooltip(Blockly.Msg.senseBox_output_safetosd_tip);
this.setHelpUrl('https://sensebox.de/books');
}
};
Blockly.Blocks['sensebox_sd_write_file'] = {
init: function () {
this.appendDummyInput()
.appendField(Blockly.Msg.senseBox_sd_write_file)
.setAlign(Blockly.ALIGN_LEFT);
this.appendValueInput('DATA')
.setCheck(null);
this.appendDummyInput('CheckboxText')
.appendField(Blockly.Msg.senseBox_output_linebreak)
.appendField(new Blockly.FieldCheckbox('TRUE'), 'linebreak');
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(getColour().sensebox);
this.setTooltip(Blockly.Msg.senseBox_output_safetosd_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_sd_open_file'],
};

View File

@ -16,14 +16,11 @@ 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, Types.NUMBER.typeId);
this.setOutput(true, Types.DECIMAL.typeName);
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;
},
}
};
/**
@ -40,14 +37,11 @@ Blockly.Blocks['sensebox_sensor_uv_light'] = {
.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.setOutput(true, Types.DECIMAL.typeName);
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;
},
}
};
/*
@ -66,14 +60,11 @@ Blockly.Blocks['sensebox_sensor_bmx055_accelerometer'] = {
.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.setOutput(true, Types.DECIMAL.typeName);
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;
},
}
};
/**
@ -91,14 +82,11 @@ Blockly.Blocks['sensebox_sensor_sds011'] = {
.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.setOutput(true, Types.DECIMAL.typeName);
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;
},
}
};
@ -121,7 +109,7 @@ Blockly.Blocks['sensebox_sensor_pressure'] = {
.appendField(Blockly.Msg.senseBox_value)
.appendField(dropdown, "NAME");
this.setColour(getColour().sensebox);
this.setOutput(true, Types.NUMBER.typeId);
this.setOutput(true, Types.DECIMAL.typeName);
this.setTooltip(Blockly.Msg.senseBox_pressure_tip);
this.setHelpUrl('https://edu.books.sensebox.de/de/projekte/diy_umweltstation/luftdruck.html');
},
@ -167,15 +155,7 @@ Blockly.Blocks['sensebox_sensor_pressure'] = {
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;
}
},
}
};
@ -193,13 +173,10 @@ Blockly.Blocks['sensebox_sensor_bme680_bsec'] = {
.setAlign(Blockly.ALIGN_RIGHT)
.appendField(Blockly.Msg.senseBox_value)
.appendField(new Blockly.FieldDropdown(dropdownOptions), "dropdown")
this.setOutput(true, Types.NUMBER.typeId);
this.setOutput(true, Types.DECIMAL.typeName);
this.setColour(getColour().sensebox);
this.setTooltip(Blockly.Msg.senseBox_bme_tip);
},
getBlockType: function () {
return Types.DECIMAL.typeId;
},
}
};
/**
@ -231,7 +208,7 @@ Blockly.Blocks['sensebox_sensor_ultrasonic_ranger'] = {
.appendField(Blockly.Msg.senseBox_ultrasonic_echo)
.appendField(new Blockly.FieldDropdown(
selectedBoard().digitalPins), 'ultrasonic_echo');
this.setOutput(true, Types.NUMBER.typeId);
this.setOutput(true, Types.NUMBER.typeName);
this.setTooltip(Blockly.Msg.senseBox_ultrasonic_tip);
this.setHelpUrl('https://sensebox.de/books');
},
@ -280,10 +257,6 @@ Blockly.Blocks['sensebox_sensor_ultrasonic_ranger'] = {
default:
break;
}
},
getBlockType: function () {
return Blockly.Types.NUMBER;
}
};
@ -300,13 +273,10 @@ Blockly.Blocks['sensebox_sensor_sound'] = {
.appendField(Blockly.Msg.senseBox_sound)
.appendField("Pin:")
.appendField(new Blockly.FieldDropdown(selectedBoard().analogPins), "PIN")
this.setOutput(true, Types.NUMBER.typeId);
this.setOutput(true, Types.NUMBER.typeName);
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 @@

View File

@ -0,0 +1,43 @@
import Blockly from 'blockly/core';
import { getColour } from '../helpers/colour';
import { getCompatibleTypes } from '../helpers/types'
Blockly.Blocks['variables_set_dynamic'] = {
init: function () {
// const type = myVar.type;
this.setColour(getColour().variables);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.appendValueInput('VALUE')
.appendField('set', 'set')
.appendField('', 'type')
.appendField(new Blockly.FieldVariable('VAR'), 'VAR')
.appendField('to');
},
onchange: function (e) {
let variableID = this.getFieldValue('VAR');
let variable = Blockly.getMainWorkspace().getVariableMap().getVariableById(variableID)
this.getField('type').setValue(variable.type);
this.getInput('VALUE').setCheck(getCompatibleTypes(variable.type));
}
}
Blockly.Blocks['variables_get_dynamic'] = {
init: function () {
this.setColour(getColour().variables);
this.appendDummyInput()
.appendField('', 'type')
.appendField(new Blockly.FieldVariable('VAR'), 'VAR');
this.setOutput(true);
},
onchange: function (e) {
let variableID = this.getFieldValue('VAR');
let variable = Blockly.getMainWorkspace().getVariableMap().getVariableById(variableID)
this.getField('type').setValue(variable.type);
}
}

View File

@ -0,0 +1,25 @@
import * as Blockly from 'blockly/core';
/**
* Function for turning the tone library on on a given pin (X).
* Arduino code: setup { pinMode(X, OUTPUT) }
* loop { tone(X, frequency) }
* @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation.
*/
Blockly.Arduino['io_tone'] = function (block) {
var pin = block.getFieldValue('TONEPIN');
var freq = Blockly.Arduino.valueToCode(block, 'FREQUENCY', Blockly.Arduino.ORDER_ATOMIC);
Blockly.Arduino.setupCode_['io_tone' + pin] = 'pinMode(' + pin + ', OUTPUT);\n';
var code = 'tone(' + pin + ',' + freq + ');\n';
return code;
};
Blockly.Arduino['io_notone'] = function (block) {
var pin = block.getFieldValue("TONEPIN");
Blockly.Arduino.setupCode_['io_tone' + pin] = 'pinMode(' + pin + ', OUTPUT);\n';
var code = 'noTone(' + pin + ');\n';
return code;
};

View File

@ -7,11 +7,15 @@ import './sensebox-web';
import './sensebox-display';
import './sensebox-lora';
import './sensebox-led';
import './sensebox-sd';
import './logic';
import './text';
import './math';
import './map';
import './io';
import './audio';
import './procedures';
import './time';
import './variables';

View File

@ -86,7 +86,37 @@ Blockly.Arduino['controls_if'] = function (Block) {
return code + '\n';
};
Blockly.Arduino['controls_ifelse'] = Blockly.Arduino['control_if'];
Blockly.Arduino['controls_ifelse'] = function (Block) {
// If/elseif/else condition.
let n = 0;
let code = '',
branchCode,
conditionCode;
do {
conditionCode =
Blockly.Arduino.valueToCode(
Block,
'IF' + n,
Blockly.Arduino.ORDER_NONE
) || 'false';
branchCode = Blockly.Arduino.statementToCode(Block, 'DO' + n);
code +=
(n > 0 ? ' else ' : '') +
'if (' +
conditionCode +
') {\n' +
branchCode +
'}';
++n;
} while (Block.getInput('IF' + n));
if (Block.getInput('ELSE')) {
branchCode = Blockly.Arduino.statementToCode(Block, 'ELSE');
code += ' else {\n' + branchCode + '}';
}
return code + '\n';
}
Blockly.Arduino['logic_negate'] = function (Block) {
// Negation.
@ -95,3 +125,30 @@ Blockly.Arduino['logic_negate'] = function (Block) {
const code = '!' + argument0;
return [code, order];
};
Blockly.Arduino['switch_case'] = function (block) {
var n = 0;
var argument = Blockly.Arduino.valueToCode(this, 'CONDITION',
Blockly.Arduino.ORDER_NONE) || '';
var branch = Blockly.Arduino.statementToCode(block, 'CASECONDITON0' + n);
var cases = '';
var default_code = '';
var DO = Blockly.Arduino.statementToCode(block, ('CASE' + n));
for (n = 0; n <= block.caseCount_; n++) {
DO = Blockly.Arduino.statementToCode(block, ('CASE' + n));
branch = Blockly.Arduino.valueToCode(block, ('CASECONDITION' + n), Blockly.Arduino.ORDER_NONE) || '0';
cases += 'case ' + branch + ':\n';
cases += DO + '\nbreak;\n';
}
if (block.defaultCount_) {
branch = Blockly.Arduino.statementToCode(block, 'ONDEFAULT');
default_code = 'default: \n' + branch + '\n break;\n';
}
var code = 'switch (' + argument + ') {\n' + cases + default_code + '}';
return code + '\n';
};

View File

@ -14,9 +14,9 @@ Blockly['Arduino']['controls_repeat_ext'] = function (Block) {
let branch = Blockly['Arduino'].statementToCode(Block, 'DO');
branch = Blockly['Arduino'].addLoopTrap(branch, Block.id);
let code = '';
const loopVar = 'simple_loop_variable';
const loopVar = 'i';
code +=
'for (' +
'for (int ' +
loopVar +
' = 1; ' +
loopVar +
@ -36,6 +36,8 @@ Blockly['Arduino']['controls_for'] = function (Block) {
Block.getFieldValue('VAR')
).name;
const branch = Blockly['Arduino'].statementToCode(Block, 'DO');
const startNumber =

View File

@ -19,9 +19,9 @@ Blockly.Arduino['arduino_functions'] = function (block) {
}
var setupBranch = Blockly.Arduino.statementToCode(block, 'SETUP_FUNC');
//var setupCode = Blockly.Arduino.scrub_(block, setupBranch); No comment block
// //var setupCode = Blockly.Arduino.scrub_(block, setupBranch); No comment block
if (setupBranch) {
Blockly.Arduino.setupCode_('userSetupCode', setupBranch, true);
Blockly.Arduino.setupCode_['mainsetup'] = setupBranch;
}
var loopBranch = statementToCodeNoTab(block, 'LOOP_FUNC');

View File

@ -0,0 +1,54 @@
import Blockly from 'blockly';
/* SD-Card Blocks using the Standard SD Library*/
/**
* Code generator for variable (X) getter.
* Arduino code: loop { X }
* @param {Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation.
*/
Blockly.Arduino.sensebox_sd_create_file = function (block) {
var filename = this.getFieldValue('Filename');
var res = filename.slice(0, 4);
Blockly.Arduino.libraries_['library_spi'] = '#include <SPI.h>';
Blockly.Arduino.libraries_['library_sd'] = '#include <SD.h>';
Blockly.Arduino.definitions_['define_' + res] = 'File dataFile' + res + ';';
Blockly.Arduino.setupCode_['sensebox_sd'] = 'SD.begin(28);';
Blockly.Arduino.setupCode_['sensebox_sd' + filename] = 'dataFile' + res + ' = SD.open("' + filename + '", FILE_WRITE);\ndataFile' + res + '.close();\n';
var code = '';
return code;
};
Blockly.Arduino.sensebox_sd_open_file = function (block) {
var filename = this.getFieldValue('Filename');
var res = filename.slice(0, 4);
var branch = Blockly.Arduino.statementToCode(block, 'SD');
var code = 'dataFile' + res + ' = SD.open("' + filename + '", FILE_WRITE);\n'
code += branch;
code += 'dataFile' + res + '.close();\n'
return code;
};
Blockly.Arduino.sensebox_sd_write_file = function (block) {
if (this.parentBlock_ != null) {
var filename = this.getSurroundParent().getFieldValue('Filename');
}
var res = filename.slice(0, 4);
var text = Blockly.Arduino.valueToCode(this, 'DATA', Blockly.Arduino.ORDER_ATOMIC) || '"Keine Eingabe"';
var linebreak = this.getFieldValue('linebreak');
if (linebreak === "TRUE") {
linebreak = "ln";
} else {
linebreak = "";
}
var code = '';
if (text === "gps.getLongitude()" || text === "gps.getLatitude()") {
code = 'dataFile' + res + '.print' + linebreak + '(' + text + ',5);\n'
}
else {
code = 'dataFile' + res + '.print' + linebreak + '(' + text + ');\n'
}
return code;
};

View File

@ -13,7 +13,7 @@ Blockly.Arduino.sensebox_telegram = function (Block) {
UniversalTelegramBot bot(BOTtoken, client);`
let code = 'testcode';
let code = '';
return code;
};

View File

@ -0,0 +1,85 @@
import * as Blockly from 'blockly/core';
/**
* Code generator for a literal String (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['text'] = function (block) {
var code = Blockly.Arduino.quote_(block.getFieldValue('TEXT'));
return [code, Blockly.Arduino.ORDER_ATOMIC];
};
/**
* Code generator for a String concatenation (X...Y). This string can be made
* up of any number of elements of any type.
* This block uses a mutator.
* String construction info: http://arduino.cc/en/Reference/StringConstructor
* Arduino code: loop { "String(X)" + ... + "String(Y)" }
* @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation.
*/
Blockly.Arduino['text_join'] = function (block) {
var code;
if (block.itemCount_ === 0) {
return ['""', Blockly.Arduino.ORDER_ATOMIC];
} else if (block.itemCount_ === 1) {
var argument0 = Blockly.Arduino.valueToCode(block, 'ADD0',
Blockly.Arduino.ORDER_UNARY_POSTFIX) || '""';
code = 'String(' + argument0 + ')';
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
} else {
var argument;
code = [];
for (var n = 0; n < block.itemCount_; n++) {
argument = Blockly.Arduino.valueToCode(
block, 'ADD' + n, Blockly.Arduino.ORDER_NONE);
if (argument === '') {
code[n] = '""';
} else {
code[n] = 'String(' + argument + ')';
}
}
code = code.join(' + ');
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
}
};
/**
* Code generator for appending text (Y) to a variable in place (X).
* String constructor info: http://arduino.cc/en/Reference/StringConstructor
* Arduino code: loop { X += String(Y) }
* @param {!Blockly.Block} block Block to generate the code from.
* @return {string} Completed code.
*/
Blockly.Arduino['text_append'] = function (block) {
// Append to a variable in place.
var varName = Blockly.Arduino.variableDB_.getName(
block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
var argument0 = Blockly.Arduino.valueToCode(block, 'TEXT',
Blockly.Arduino.ORDER_UNARY_POSTFIX);
if (argument0 === '') {
argument0 = '""';
} else {
argument0 = 'String(' + argument0 + ')';
}
return varName + ' += ' + argument0 + ';\n';
};
/**
* Code generator to get the length of a string (X).
* String length info: http://arduino.cc/en/Reference/StringLength
* Arduino code: loop { String(X).length() }
* @param {!Blockly.Block} block Block to generate the code from.
* @return {array} Completed code with order of operation.
*/
Blockly.Arduino['text_length'] = function (block) {
var argument0 = Blockly.Arduino.valueToCode(block, 'VALUE',
Blockly.Arduino.ORDER_UNARY_POSTFIX) || '""';
var code = 'String(' + argument0 + ').length()';
return [code, Blockly.Arduino.ORDER_UNARY_POSTFIX];
};

View File

@ -0,0 +1,33 @@
import Blockly from 'blockly';
const setVariableFunction = function (defaultValue) {
return function (block) {
const variableName = Blockly['Arduino'].variableDB_.getName(
block.getFieldValue('VAR'),
Blockly.Variables.NAME_TYPE
);
const variableValue = Blockly['Arduino'].valueToCode(
block,
'VALUE',
Blockly['Arduino'].ORDER_ATOMIC
);
const allVars = Blockly.getMainWorkspace().getVariableMap().getAllVariables();
const myVar = allVars.filter(v => v.name === variableName)[0]
Blockly.Arduino.variables_[myVar + myVar.type] = myVar.type + " " + myVar.name + ';\n';
return variableName + ' = ' + (variableValue || defaultValue) + ';\n';
};
};
const getVariableFunction = function (block) {
const variableName = Blockly['Arduino'].variableDB_.getName(
block.getFieldValue('VAR'),
Blockly.Variables.NAME_TYPE
);
return [variableName, Blockly['Arduino'].ORDER_ATOMIC];
};
Blockly['Arduino']['variables_set_dynamic'] = setVariableFunction()
Blockly['Arduino']['variables_get_dynamic'] = getVariableFunction;

View File

@ -7,6 +7,9 @@ const colours = {
io: 60,
procedures: 290,
time: 140,
text: 160,
variables: 330,
audio: 250,
}

View File

@ -12,57 +12,54 @@
/** Single character. */
export const CHARACTER = {
typeId: 'Character',
typeName: 'char',
typeMsgName: 'ARD_TYPE_CHAR',
compatibleTypes: []
}
export const BOOLEAN = {
typeId: 'Boolean',
typeMsgName: 'ARD_TYPE_BOOL',
compatibleTypes: ['Boolean']
}
/** Text string. */
export const TEXT = {
typeId: 'Text',
typeName: 'String',
typeMsgName: 'ARD_TYPE_TEXT',
compatibleTypes: []
}
/** Short integer number. */
export const SHORT_NUMBER = {
typeId: 'Short Number',
typeId: 'Short_Number',
typeName: 'int',
typeMsgName: 'ARD_TYPE_SHORT',
compatibleTypes: [] // Circular dependencies, add after all declarations
}
/** Integer number. */
export const NUMBER = {
typeId: 'Number',
typeName: 'int',
typeMsgName: 'ARD_TYPE_NUMBER',
compatibleTypes: ['Number'] // Circular dependencies, add after all declarations
}
/** Large integer number. */
export const LARGE_NUMBER = {
typeId: 'Large Number',
typeName: 'long',
typeMsgName: 'ARD_TYPE_LONG',
compatibleTypes: [] // Circular dependencies, add after all declarations
}
/** Decimal/floating point number. */
export const DECIMAL = {
typeId: 'Decimal',
typeName: 'float',
typeMsgName: 'ARD_TYPE_DECIMAL',
compatibleTypes: [BOOLEAN.typeId,
NUMBER,
SHORT_NUMBER,
LARGE_NUMBER]
}
/** Array/List of items. */
export const ARRAY = {
typeId: 'Array',
typeName: 'array',
typeMsgName: 'ARD_TYPE_ARRAY',
compatibleTypes: []
}
@ -70,15 +67,15 @@ export const ARRAY = {
/** Null indicate there is no type. */
export const NULL = {
typeId: 'Null',
typeName: 'void',
typeMsgName: 'ARD_TYPE_NULL',
compatibleTypes: []
}
/** Type not defined, or not yet defined. */
export const UNDEF = {
typeId: 'Undefined',
typeName: 'undef',
typeMsgName: 'ARD_TYPE_UNDEF',
compatibleTypes: []
}
/** Set when no child block (meant to define the variable type) is connected. */
@ -88,6 +85,24 @@ export const CHILD_BLOCK_MISSING = {
compatibleTypes: []
}
const compatibleTypes = {
boolean: ['boolean'],
int: ['int'],
char: ['char'],
string: ['String'],
void: ['void'],
long: ['int', 'long'],
double: ['int', 'long', 'double'],
float: ['int', 'long', 'double', 'float']
}
export const getCompatibleTypes = (type) => {
return compatibleTypes[type];
};
export const VARIABLE_TYPES = [['SHORT_NUMBER', 'char'], ['NUMBER', 'int'], ['DECIMAL', 'long'], ['TEXT', 'String'], ['CHARACTER', 'char'], ['BOOLEAN', 'boolean'], ['NULL', 'void'], ['UNDEF', 'undefined']];
// /**
// * Some Types have circular dependencies on their compatibilities, so add them
// * after declaration.

View File

@ -3,169 +3,202 @@ import { Block, Value, Field, Shadow, Category } from '../';
import { getColour } from '../helpers/colour'
import '@blockly/block-plus-minus';
import { TypedVariableModal } from '@blockly/plugin-typed-variable-modal';
import * as Blockly from 'blockly/core';
import BlocklyComponent from '../BlocklyComponent';
class Toolbox extends React.Component {
componentDidUpdate() {
this.props.workspace.registerToolboxCategoryCallback('CREATE_TYPED_VARIABLE', this.createFlyout);
const typedVarModal = new TypedVariableModal(this.props.workspace, 'callbackName', [['SHORT_NUMBER', 'char'], ['NUMBER', 'int'], ['DECIMAL', 'float'], ['TEXT', 'String'], ['CHARACTER', 'char'], ['BOOLEAN', 'boolean'], ['NULL', 'void'], ['UNDEF', 'undefined']]);
typedVarModal.init();
}
createFlyout(workspace) {
let xmlList = [];
// Add your button and give it a callback name.
const button = document.createElement('button');
button.setAttribute('text', 'Create Typed Variable');
button.setAttribute('callbackKey', 'callbackName');
xmlList.push(button);
// This gets all the variables that the user creates and adds them to the
// flyout.
const blockList = Blockly.VariablesDynamic.flyoutCategoryBlocks(workspace);
xmlList = xmlList.concat(blockList);
return xmlList;
};
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 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="SD" colour={getColour().sensebox}>
<Block type="sensebox_sd_create_file" />
<Block type="sensebox_sd_open_file" />
<Block type="sensebox_sd_write_file" />
</Category>
<Category name="LED" colour={getColour().sensebox}>
<Block type="sensebox_rgb_led" />
<Block type="sensebox_led" />
</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="openSenseMap" colour={getColour().sensebox}>
<Block type="sensebox_osem_connection" />
<Block type="sensebox_send_to_osem" />
</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 name="LED" colour={getColour().sensebox}>
<Block type="sensebox_rgb_led" />
<Block type="sensebox_led" />
<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 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 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 name="Logic" colour={getColour().logic}>
@ -175,6 +208,7 @@ class Toolbox extends React.Component {
<Block type="logic_operation" />
<Block type="logic_negate" />
<Block type="logic_boolean" />
<Block type="switch_case" />
</Category>
<Category id="loops" name="Loops" colour={getColour().loops}>
<Block type="controls_repeat_ext">
@ -204,6 +238,17 @@ class Toolbox extends React.Component {
</Block>
<Block type="controls_flow_statements" />
</Category>
<Category id="text" name="Text" colour={getColour().text}>
<Block type="text" />
<Block type="text_join" />
<Block type="text_append">
<Value name="TEXT">
<Block type="text" />
</Value>
</Block>
<Block type="text_length" />
<Block type="text_isEmpty" />
</Category>
<Category id="time" name="Time" colour={getColour().time}>
<Block type="time_delay">
<Value name="DELAY_TIME_MILI">
@ -267,6 +312,17 @@ class Toolbox extends React.Component {
<Block type="math_random_float"></Block>
<Block type="base_map"></Block>
</Category>
<Category id="audio" name="Audio" colour={getColour().audio}>
<Block type="io_tone">
<Value name="FREQUENCY">
<Shadow type="math_number">
<Field name="NUM">220</Field>
</Shadow>
</Value>
</Block>
<Block type="io_notone"></Block>
</Category>
<Category name="Variablen" colour={getColour().variables} custom="CREATE_TYPED_VARIABLE"></Category>;
<sep></sep>
<Category name="Input/Output" colour={getColour().io}>
<Block type="io_digitalwrite"></Block>

View File

@ -65,7 +65,7 @@ class Compile extends Component {
};
fetch(`${process.env.REACT_APP_COMPILER_URL}/compile`, {
method: "POST",
headers: {'Content-Type': 'application/json'},
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => response.json())
@ -158,4 +158,5 @@ const mapStateToProps = state => ({
name: state.workspace.name
});
export default connect(mapStateToProps, { workspaceName })(withStyles(styles, {withTheme: true})(Compile));

11537
yarn.lock Normal file

File diff suppressed because it is too large Load Diff