diff --git a/src/components/Blockly/blocks/sensebox-sd.js b/src/components/Blockly/blocks/sensebox-sd.js index febdf4c..52d4bbf 100644 --- a/src/components/Blockly/blocks/sensebox-sd.js +++ b/src/components/Blockly/blocks/sensebox-sd.js @@ -1,80 +1,156 @@ -import * as Blockly from 'blockly/core'; -import { getColour } from '../helpers/colour'; +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_sd_open_file_tooltip); + this.setHelpUrl("https://docs.sensebox.de/hardware/bee-sd/"); + }, +}; -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_sd_open_file_tooltip); - this.setHelpUrl('https://docs.sensebox.de/hardware/bee-sd/'); +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_sd_create_file_tooltip); + this.setHelpUrl("https://docs.sensebox.de/hardware/bee-sd/"); + }, +}; + +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_sd_write_file_tooltip); + this.setHelpUrl("https://docs.sensebox.de/hardware/bee-sd/"); + }, + /** + * 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"], }; -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_sd_create_file_tooltip); - this.setHelpUrl('https://docs.sensebox.de/hardware/bee-sd/'); +Blockly.Blocks["sensebox_sd_osem"] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_osem_connection_tip); + this.setHelpUrl(""); + this.setColour(getColour().sensebox); + this.appendDummyInput() + .setAlign(Blockly.ALIGN_LEFT) + .appendField("Create CSV for openSenseMap"); + 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.appendValueInput("timeStamp", "Number").appendField( + Blockly.Msg.senseBox_gps_timeStamp + ); + this.appendStatementInput("DO") + .appendField(Blockly.Msg.senseBox_sensor) + .setCheck(null); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, + 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 + ); } -}; -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_sd_write_file_tooltip); - this.setHelpUrl('https://docs.sensebox.de/hardware/bee-sd/'); - }, - /** - * 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'], + if (input === "Stationary" && extraFieldExist !== null) { + this.removeInput("lat"); + this.removeInput("lng"); + this.removeInput("altitude"); + } + }, +}; +Blockly.Blocks["sensebox_sd_save_for_osem"] = { + init: function () { + this.setTooltip(Blockly.Msg.senseBox_send_to_osem_tip); + this.setHelpUrl(""); + this.setColour(getColour().sensebox); + this.appendDummyInput().appendField(Blockly.Msg.sensebox_sd_save_for_osem); + this.appendValueInput("Value") + .setAlign(Blockly.ALIGN_LEFT) + .appendField("Phänomen") + .appendField(new Blockly.FieldTextInput("sensorID"), "SensorID"); + this.setPreviousStatement(true, null); + this.setNextStatement(true, null); + }, }; diff --git a/src/components/Blockly/blocks/sensebox-sensors.js b/src/components/Blockly/blocks/sensebox-sensors.js index d12d70a..b7ffa3a 100644 --- a/src/components/Blockly/blocks/sensebox-sensors.js +++ b/src/components/Blockly/blocks/sensebox-sensors.js @@ -412,8 +412,9 @@ Blockly.Blocks["sensebox_gps"] = { [Blockly.Msg.senseBox_gps_lat, "latitude"], [Blockly.Msg.senseBox_gps_lng, "longitude"], [Blockly.Msg.senseBox_gps_alt, "altitude"], + [Blockly.Msg.senseBox_gps_timeStamp, "timestamp"], + [Blockly.Msg.senseBox_gps_speed, "speed"], ["pDOP", "pDOP"], - ["Timestamp", "timestamp"], ["Fix Type", "fixType"], ]; this.appendDummyInput().appendField("GPS Modul"); diff --git a/src/components/Blockly/generator/sensebox-rtc.js b/src/components/Blockly/generator/sensebox-rtc.js index 66bf2de..1c3f5e3 100644 --- a/src/components/Blockly/generator/sensebox-rtc.js +++ b/src/components/Blockly/generator/sensebox-rtc.js @@ -79,18 +79,16 @@ Blockly.Arduino.sensebox_rtc_get_timestamp = function () { Blockly.Arduino.setupCode_[ "rtc.batterySwitchOver" ] = `rtc.batterySwitchOver(1);`; - Blockly.Arduino.loopCodeOnce_[ - "rtc_variables" - ] = `uint8_t sec, min, hour, day, month;\nuint16_t year;`; Blockly.Arduino.variables_["rtc_timestamp"] = `char timestamp[20];`; - Blockly.Arduino.loopCodeOnce_[ - "rtc_get" - ] = `rtc.get(&sec, &min, &hour, &day, &month, &year);`; - - Blockly.Arduino.loopCodeOnce_[ - "" - ] = `sprintf(timestamp, "%02d-%02d-%02dT%02d:%02d:%02dZ", year, month, day, hour, min, sec);`; - - var code = `timestamp`; + Blockly.Arduino.codeFunctions_["getTimeStamp"] = ` +char* getTimeStamp() { +uint8_t sec, min, hour, day, month; + uint16_t year; + rtc.get(&sec, &min, &hour, &day, &month, &year); + sprintf(timestamp, "%02d-%02d-%02dT%02d:%02d:%02dZ", year, month, day, hour, min, sec); + return timestamp; + } + `; + var code = `getTimeStamp()`; return [code, Blockly.Arduino.ORDER_ATOMIC]; }; diff --git a/src/components/Blockly/generator/sensebox-sd.js b/src/components/Blockly/generator/sensebox-sd.js index 1926d74..b7ffa0f 100644 --- a/src/components/Blockly/generator/sensebox-sd.js +++ b/src/components/Blockly/generator/sensebox-sd.js @@ -1,5 +1,4 @@ -import Blockly from 'blockly'; - +import Blockly from "blockly"; /* SD-Card Blocks using the Standard SD Library*/ /** @@ -10,45 +9,202 @@ import Blockly from 'blockly'; */ 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 '; - Blockly.Arduino.libraries_['library_sd'] = '#include '; - 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; + var filename = this.getFieldValue("Filename"); + var res = filename.slice(0, 4); + Blockly.Arduino.libraries_["library_spi"] = "#include "; + Blockly.Arduino.libraries_["library_sd"] = "#include "; + 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; + 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; + 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; +}; + +Blockly.Arduino.sensebox_sd_osem = function () { + var type = this.getFieldValue("type"); + var blocks = this.getDescendants(); + var branch = Blockly.Arduino.statementToCode(this, "DO"); + var count = 0; + if (blocks !== undefined) { + for (var i = 0; i < blocks.length; i++) { + if (blocks[i].type === "sensebox_sd_save_for_osem") { + count++; + } + } + } + var num_sensors = count; + var timestamp = Blockly.Arduino.valueToCode( + this, + "timeStamp", + Blockly.Arduino.ORDER_ATOMIC + ); + Blockly.Arduino.definitions_["num_sensors"] = + "static const uint8_t NUM_SENSORS = " + num_sensors + ";"; + + 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;`; + if (type === "Stationary") { + Blockly.Arduino.functionNames_["addMeasurement"] = ` +void addMeasurement(const char *sensorId, float value) { + measurements[num_measurements].sensorId = sensorId; + measurements[num_measurements].value = value; + num_measurements++; + } +`; + Blockly.Arduino.functionNames_["writeMeasurementsToSdCard"] = ` +void writeMeasurementsToSdCard(char* timeStamp) { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { +sprintf_P(buffer, PSTR("%s,%9.2f,%s"), measurements[i].sensorId, measurements[i].value, timeStamp); + // transmit buffer to client + dataFileData.print(buffer); + Serial.print(buffer); + } + // reset num_measurements + num_measurements = 0; +} +`; + Blockly.Arduino.functionNames_["saveValues"] = ` +void saveValues() { + + + // send measurements + writeMeasurementsToSdCard(${timestamp}); + num_measurements = 0; +} +`; + var code = ""; + code += branch; + code += "saveValues();"; + } else if (type === "Mobile") { + /** + * add mobile functions here + */ + Blockly.Arduino.libraries_["dtostrf.h"] = "#include "; + var lat = Blockly.Arduino.valueToCode( + this, + "lat", + Blockly.Arduino.ORDER_ATOMIC + ); + var lng = Blockly.Arduino.valueToCode( + this, + "lng", + Blockly.Arduino.ORDER_ATOMIC + ); + // var altitude = Blockly.Arduino.valueToCode( + // this, + // "altitude", + // Blockly.Arduino.ORDER_ATOMIC + // ); + Blockly.Arduino.definitions_["num_sensors"] = + "static const uint8_t NUM_SENSORS = " + num_sensors + ";"; + + 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.functionNames_["addMeasurement"] = ` +void addMeasurement(const char *sensorId, float value) { + measurements[num_measurements].sensorId = sensorId; + measurements[num_measurements].value = value; + num_measurements++; + } + `; + Blockly.Arduino.functionNames_["writeMeasurementsToSdCard"] = ` +void writeMeasurementsToSdCard(char* timeStamp, uint32_t latitudes, uint32_t longitudes) { + // iterate throug the measurements array + for (uint8_t i = 0; i < num_measurements; i++) { + char lng[20]; + char lat[20]; + float longitude = longitudes / (float)10000000; + float latitude = latitudes / (float)10000000; + dtostrf(longitude, 2, 7, lng); + dtostrf(latitude, 1, 7, lat); + sprintf_P(buffer, PSTR("%s,%9.2f,%s,%02s,%02s"), measurements[i].sensorId, measurements[i].value, timeStamp, lng, lat); + // transmit buffer to client + dataFileData.print(buffer); + Serial.print(buffer); + } + // reset num_measurements + num_measurements = 0; + } + `; + Blockly.Arduino.functionNames_["saveValues"] = ` + void saveValues() { + // send measurements + writeMeasurementsToSdCard(${timestamp}, ${lat}, ${lng}); + num_measurements = 0; + } + `; + code = ""; + code += branch; + code += "saveValues();\n"; + } + return code; +}; + +Blockly.Arduino.sensebox_sd_save_for_osem = function (block) { + var code = ""; + var sensor_id = this.getFieldValue("SensorID"); + var id = sensor_id.slice(-3).toUpperCase(); + var sensor_value = + Blockly.Arduino.valueToCode(block, "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"; + console.log(code); + return code; }; diff --git a/src/components/Blockly/msg/de/sensebox-sd.js b/src/components/Blockly/msg/de/sensebox-sd.js index 2e74c8e..c0d8e81 100644 --- a/src/components/Blockly/msg/de/sensebox-sd.js +++ b/src/components/Blockly/msg/de/sensebox-sd.js @@ -1,13 +1,18 @@ export const SD = { - /** - * SD-Block - */ - senseBox_sd_create_file: "Erstelle Datei auf SD-Karte", - senseBox_sd_write_file: "Schreibe Daten auf SD-Karte", - senseBox_sd_open_file: "Öffne eine Datei auf der SD-Karte", - senseBox_sd_create_file_tooltip: "Erstellt eine Datei auf der Karte. Stecke das SD-Bee auf den Steckplatz **XBEE2**. Die **maximale** Länge des Dateinamen sind **8 Zeichen**. Die Datei sollte zuerst im *Setup()* erstellt werden", - senseBox_sd_write_file_tooptip: "Schreibe Daten auf die SD-Karte. Beachte, dass die Datei zuerst geöffnet werden muss.", - senseBox_sd_open_file_tooltip: "Öffne die Datei auf der SD-Karte, um Dateien zu speichern. Am Ende der Schleife wird die Datei automatisch wieder geschlossen.", - sensebox_sd_filename: "Daten", - senseBox_sd_decimals: "Dezimalen", -} \ No newline at end of file + /** + * SD-Block + */ + senseBox_sd_create_file: "Erstelle Datei auf SD-Karte", + senseBox_sd_write_file: "Schreibe Daten auf SD-Karte", + senseBox_sd_open_file: "Öffne eine Datei auf der SD-Karte", + senseBox_sd_create_file_tooltip: + "Erstellt eine Datei auf der Karte. Stecke das SD-Bee auf den Steckplatz **XBEE2**. Die **maximale** Länge des Dateinamen sind **8 Zeichen**. Die Datei sollte zuerst im *Setup()* erstellt werden", + senseBox_sd_write_file_tooptip: + "Schreibe Daten auf die SD-Karte. Beachte, dass die Datei zuerst geöffnet werden muss.", + senseBox_sd_open_file_tooltip: + "Öffne die Datei auf der SD-Karte, um Dateien zu speichern. Am Ende der Schleife wird die Datei automatisch wieder geschlossen.", + sensebox_sd_filename: "Daten", + senseBox_sd_decimals: "Dezimalen", + sensebox_sd_osem: "Erstelle CSV für openSenseMap", + sensebox_sd_save_for_osem: "Speichere als CSV für openSenseMap", +}; diff --git a/src/components/Blockly/toolbox/Toolbox.js b/src/components/Blockly/toolbox/Toolbox.js index f34d367..27285fb 100644 --- a/src/components/Blockly/toolbox/Toolbox.js +++ b/src/components/Blockly/toolbox/Toolbox.js @@ -102,6 +102,13 @@ class Toolbox extends React.Component { + + + + + + +