From 19849d68ab91bd4f908007cfe26287ab835afa84 Mon Sep 17 00:00:00 2001 From: Mario Pesch Date: Wed, 5 Jan 2022 16:24:20 +0100 Subject: [PATCH] add a new code Editor --- package-lock.json | 65 +++++ package.json | 1 + src/components/CodeEditor/CodeEditor.js | 206 +++++++++++++++ src/components/CodeEditor/Compile.js | 338 ++++++++++++++++++++++++ src/components/CodeEditor/Sidebar.js | 114 ++++++++ src/components/Navbar.js | 5 + src/components/Route/Routes.js | 4 + src/data/arduinoExamples.js | 16 ++ src/data/versions.js | 104 ++++++++ yarn.lock | 29 +- 10 files changed, 880 insertions(+), 2 deletions(-) create mode 100644 src/components/CodeEditor/CodeEditor.js create mode 100644 src/components/CodeEditor/Compile.js create mode 100644 src/components/CodeEditor/Sidebar.js create mode 100644 src/data/arduinoExamples.js create mode 100644 src/data/versions.js diff --git a/package-lock.json b/package-lock.json index 904c851..04700ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@fortawesome/free-solid-svg-icons": "^5.14.0", "@fortawesome/react-fontawesome": "^0.1.11", "@material-ui/core": "^4.11.0", + "@monaco-editor/react": "^4.3.1", "@sentry/react": "^6.0.0", "@sentry/tracing": "^6.0.0", "@testing-library/jest-dom": "^4.2.4", @@ -3120,6 +3121,31 @@ "node": ">=8.0.0" } }, + "node_modules/@monaco-editor/loader": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.2.0.tgz", + "integrity": "sha512-cJVCG/T/KxXgzYnjKqyAgsKDbH9mGLjcXxN6AmwumBwa2rVFkwvGcUj1RJtD0ko4XqLqJxwqsN/Z/KURB5f1OQ==", + "dependencies": { + "state-local": "^1.0.6" + }, + "peerDependencies": { + "monaco-editor": ">= 0.21.0 < 1" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.3.1.tgz", + "integrity": "sha512-f+0BK1PP/W5I50hHHmwf11+Ea92E5H1VZXs+wvKplWUWOfyMa1VVwqkJrXjRvbcqHL+XdIGYWhWNdi4McEvnZg==", + "dependencies": { + "@monaco-editor/loader": "^1.2.0", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", @@ -16643,6 +16669,12 @@ "node": "*" } }, + "node_modules/monaco-editor": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.31.1.tgz", + "integrity": "sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q==", + "peer": true + }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -21503,6 +21535,11 @@ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "node_modules/static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -27515,6 +27552,23 @@ "react-is": "^16.8.0" } }, + "@monaco-editor/loader": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.2.0.tgz", + "integrity": "sha512-cJVCG/T/KxXgzYnjKqyAgsKDbH9mGLjcXxN6AmwumBwa2rVFkwvGcUj1RJtD0ko4XqLqJxwqsN/Z/KURB5f1OQ==", + "requires": { + "state-local": "^1.0.6" + } + }, + "@monaco-editor/react": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.3.1.tgz", + "integrity": "sha512-f+0BK1PP/W5I50hHHmwf11+Ea92E5H1VZXs+wvKplWUWOfyMa1VVwqkJrXjRvbcqHL+XdIGYWhWNdi4McEvnZg==", + "requires": { + "@monaco-editor/loader": "^1.2.0", + "prop-types": "^15.7.2" + } + }, "@nodelib/fs.scandir": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", @@ -38126,6 +38180,12 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", "integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==" }, + "monaco-editor": { + "version": "0.31.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.31.1.tgz", + "integrity": "sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q==", + "peer": true + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -42087,6 +42147,11 @@ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" }, + "state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", diff --git a/package.json b/package.json index 3ceca2c..8eaeb1a 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@fortawesome/free-solid-svg-icons": "^5.14.0", "@fortawesome/react-fontawesome": "^0.1.11", "@material-ui/core": "^4.11.0", + "@monaco-editor/react": "^4.3.1", "@sentry/react": "^6.0.0", "@sentry/tracing": "^6.0.0", "@testing-library/jest-dom": "^4.2.4", diff --git a/src/components/CodeEditor/CodeEditor.js b/src/components/CodeEditor/CodeEditor.js new file mode 100644 index 0000000..75d2fb6 --- /dev/null +++ b/src/components/CodeEditor/CodeEditor.js @@ -0,0 +1,206 @@ +import React from "react"; +import { useState, useRef } from "react"; +import { default as MonacoEditor } from "@monaco-editor/react"; +import { withRouter } from "react-router-dom"; +import { Button, Grid } from "@material-ui/core"; +import Blockly from "blockly/core"; +import Divider from "@material-ui/core/Divider"; +import { saveAs } from "file-saver"; +import Drawer from "@material-ui/core/Drawer"; +import Sidebar from "./Sidebar"; +import Dialog from "../Dialog"; + +const CodeEditor = (props) => { + const [fileHandle, setFileHandle] = useState(); + const [fileContent, setFileContent] = useState(""); + const [progress, setProgress] = useState(false); + const [id, setId] = useState(""); + const [open, setOpen] = useState(false); + const [error, setError] = useState(""); + const editorRef = useRef(null); + + const compile = () => { + setProgress(true); + const data = { + board: process.env.REACT_APP_BOARD, + sketch: editorRef.current.getValue(), + }; + 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); + if (data.code === "Internal Server Error") { + setProgress(false); + setOpen(true); + setError(data.message); + } + setProgress(false); + const result = data.data.id; + setId(result); + console.log(result); + const filename = "sketch"; + window.open( + `${process.env.REACT_APP_COMPILER_URL}/download?id=${result}&board=${process.env.REACT_APP_BOARD}&filename=${filename}`, + "_self" + ); + }) + .catch((err) => { + console.log(err); + }); + }; + + const saveIno = () => { + var filename = "sketch"; + var code = editorRef.current.getValue(); + + filename = `${filename}.ino`; + var blob = new Blob([code], { type: "text/plain;charset=utf-8" }); + saveAs(blob, filename); + }; + + const openIno = async () => { + const [myFileHandle] = await window.showOpenFilePicker(); + setFileHandle(myFileHandle); + + const file = await myFileHandle.getFile(); + const contents = await file.text(); + setFileContent(contents); + }; + + const toggleDrawer = (anchor, open) => (event) => { + if ( + event.type === "keydown" && + (event.key === "Tab" || event.key === "Shift") + ) { + return; + } + + setOpen(false); + }; + + const loadCode = () => { + editorRef.current.setValue("test"); + }; + + return ( +
+ + +

+ {Blockly.Msg.drawer_ideerror_head} +

+

+ {Blockly.Msg.drawer_ideerror_text} +

+ +

+ {" "} + {`${error}`}{" "} +

+
+ +

Code Editor

+ { + editorRef.current = editor; + }} + /> +
+ + + + + + + +
{Blockly.Msg.tabletDialog_text}
+
+ {Blockly.Msg.tabletDialog_more}{" "} + + https://sensebox.de/app + +
+
+
+
+
+ ); +}; + +export default withRouter(CodeEditor); diff --git a/src/components/CodeEditor/Compile.js b/src/components/CodeEditor/Compile.js new file mode 100644 index 0000000..1bea26c --- /dev/null +++ b/src/components/CodeEditor/Compile.js @@ -0,0 +1,338 @@ +import React, { Component } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { workspaceName } from "../../actions/workspaceActions"; + +import { detectWhitespacesAndReturnReadableResult } from "../../helpers/whitespace"; + +import { withStyles } from "@material-ui/core/styles"; +import Button from "@material-ui/core/Button"; +import Backdrop from "@material-ui/core/Backdrop"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import IconButton from "@material-ui/core/IconButton"; +import Tooltip from "@material-ui/core/Tooltip"; +import Divider from "@material-ui/core/Divider"; +import { faClipboardCheck } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import * as Blockly from "blockly/core"; +import Copy from "../copy.svg"; +import Prism from "prismjs"; +import "prismjs/themes/prism.css"; +import "prismjs/plugins/line-numbers/prism-line-numbers"; +import "prismjs/plugins/line-numbers/prism-line-numbers.css"; +import MuiDrawer from "@material-ui/core/Drawer"; +import Dialog from "../Dialog"; + +const styles = (theme) => ({ + backdrop: { + zIndex: theme.zIndex.drawer + 1, + color: "#fff", + }, + iconButton: { + backgroundColor: theme.palette.button.compile, + color: theme.palette.primary.contrastText, + width: "40px", + height: "40px", + "&:hover": { + backgroundColor: theme.palette.button.compile, + color: theme.palette.primary.contrastText, + }, + }, + button: { + backgroundColor: theme.palette.button.compile, + color: theme.palette.primary.contrastText, + "&:hover": { + backgroundColor: theme.palette.button.compile, + color: theme.palette.primary.contrastText, + }, + }, +}); + +const Drawer = withStyles((theme) => ({ + paperAnchorBottom: { + backgroundColor: "black", + height: "20vH", + }, +}))(MuiDrawer); + +class Compile extends Component { + constructor(props) { + super(props); + this.state = { + progress: false, + open: false, + file: false, + title: "", + content: "", + name: props.name, + error: "", + appLink: "", + appDialog: false, + }; + } + + componentDidMount() { + Prism.highlightAll(); + } + + componentDidUpdate(props) { + if (props.name !== this.props.name) { + this.setState({ name: this.props.name }); + } + Prism.highlightAll(); + } + + compile = () => { + this.setState({ progress: true }); + 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); + if (data.code === "Internal Server Error") { + this.setState({ + progress: false, + file: false, + open: true, + title: Blockly.Msg.compiledialog_headline, + content: Blockly.Msg.compiledialog_text, + error: data.message, + }); + } + this.setState({ id: data.data.id }, () => { + this.createFileName(); + }); + }) + .catch((err) => { + console.log(err); + //this.setState({ progress: false, file: false, open: true, title: Blockly.Msg.compiledialog_headline, content: Blockly.Msg.compiledialog_text }); + }); + }; + + download = () => { + const id = this.state.id; + const filename = detectWhitespacesAndReturnReadableResult(this.state.name); + this.toggleDialog(); + this.props.workspaceName(this.state.name); + window.open( + `${process.env.REACT_APP_COMPILER_URL}/download?id=${id}&board=${process.env.REACT_APP_BOARD}&filename=${filename}`, + "_self" + ); + this.setState({ progress: false }); + }; + + toggleDialog = () => { + this.setState({ open: !this.state, progress: false, appDialog: false }); + }; + + createFileName = () => { + if (this.props.platform === true) { + const filename = detectWhitespacesAndReturnReadableResult( + this.state.name + ); + this.setState({ + link: `blocklyconnect-app://sketch/${filename}/${this.state.id}`, + }); + this.setState({ appDialog: true }); + } else { + if (this.state.name) { + this.download(); + } else { + this.setState({ + file: true, + open: true, + title: "Projekt kompilieren", + content: + "Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf 'Eingabe'.", + }); + } + } + + // if (this.state.name) { + // this.download(); + // } else { + // this.setState({ + // file: true, + // open: true, + // title: "Projekt kompilieren", + // content: + // "Bitte gib einen Namen für die Bennenung des zu kompilierenden Programms ein und bestätige diesen mit einem Klick auf 'Eingabe'.", + // }); + // } + }; + + setFileName = (e) => { + this.setState({ name: e.target.value }); + }; + + toggleDrawer = (anchor, open) => (event) => { + if ( + event.type === "keydown" && + (event.key === "Tab" || event.key === "Shift") + ) { + return; + } + + this.setState({ open: false }); + }; + + render() { + return ( +
+ {this.props.iconButton ? ( + + this.compile()} + > + + + + ) : ( + + )} + + {this.props.platform === false ? ( + +
+ copyimage +

{Blockly.Msg.compile_overlay_head}

+

{Blockly.Msg.compile_overlay_text}

+

+ {Blockly.Msg.compile_overlay_help} + + FAQ + +

+ +
+
+ ) : ( + +
+ {/* copyimage */} +

Dein Code wird kompiliert!

+

übertrage ihn anschließend mithlfe der senseBoxConnect-App

+

+ {Blockly.Msg.compile_overlay_help} + + FAQ + +

+ +
+
+ )} + +

+ {Blockly.Msg.drawer_ideerror_head} +

+

+ {Blockly.Msg.drawer_ideerror_text} +

+ +

+ {" "} + {`${this.state.error}`}{" "} +

+
+ +
+

Dein Code wurde erfolgreich kompiliert

+ + + +
+
+
+ ); + } +} + +Compile.propTypes = { + arduino: PropTypes.string.isRequired, + name: PropTypes.string, + workspaceName: PropTypes.func.isRequired, + platform: PropTypes.bool.isRequired, +}; + +const mapStateToProps = (state) => ({ + arduino: state.workspace.code.arduino, + name: state.workspace.name, + platform: state.general.platform, +}); + +export default connect(mapStateToProps, { workspaceName })( + withStyles(styles, { withTheme: true })(Compile) +); diff --git a/src/components/CodeEditor/Sidebar.js b/src/components/CodeEditor/Sidebar.js new file mode 100644 index 0000000..e051c71 --- /dev/null +++ b/src/components/CodeEditor/Sidebar.js @@ -0,0 +1,114 @@ +import React from "react"; +import Blockly from "blockly"; +import Accordion from "@material-ui/core/Accordion"; +import AccordionSummary from "@material-ui/core/AccordionSummary"; +import AccordionDetails from "@material-ui/core/AccordionDetails"; +import Typography from "@material-ui/core/Typography"; +import { LibraryVersions } from "../../data/versions.js"; +import { ArduinoExamples } from "../../data/arduinoExamples.js"; +import Editor, { useMonaco } from "@monaco-editor/react"; +import { Button } from "@material-ui/core"; +import Dialog from "../Dialog"; + +const Sidebar = () => { + const [alert, setAlert] = React.useState(false); + + const monaco = useMonaco(); + const loadCode = (code) => { + console.log(code); + console.log(monaco); + const defaultCode = ` +void setup () { + +} + +void loop(){ + +}`; + var currentCode = monaco.editor.getModels()[0].getValue(); + + setAlert(true); + monaco.editor.getModels()[0].setValue(code); + }; + + const toggleDialog = () => { + setAlert(false); + }; + + return ( +
+ + + Beispiele + + + + {ArduinoExamples().map((object, i) => { + return ( + + ); + })} + + + + + + Installierte Libraries + + + +

+ For Dokumentation take a look at the installed libraries and their + source +

+ {LibraryVersions().map((object, i) => { + return ( +

+ + {object.library} {object.version} + +

+ ); + })} +
+
+ toggleDialog()} + onClick={() => toggleDialog()} + button={Blockly.Msg.button_close} + > +
{Blockly.Msg.tabletDialog_text}
+
+ {Blockly.Msg.tabletDialog_more}{" "} + + https://sensebox.de/app + +
+
+
+
+ ); +}; + +export default Sidebar; diff --git a/src/components/Navbar.js b/src/components/Navbar.js index 8977637..10e3874 100644 --- a/src/components/Navbar.js +++ b/src/components/Navbar.js @@ -230,6 +230,11 @@ class Navbar extends Component { icon: faLightbulb, link: "/gallery", }, + { + text: "CodeEditor", + icon: faLightbulb, + link: "/codeeditor", + }, { text: Blockly.Msg.navbar_projects, icon: faLayerGroup, diff --git a/src/components/Route/Routes.js b/src/components/Route/Routes.js index 8bd9239..844fb66 100644 --- a/src/components/Route/Routes.js +++ b/src/components/Route/Routes.js @@ -24,6 +24,7 @@ import Login from "../User/Login"; import Account from "../User/Account"; import News from "../News"; import Faq from "../Faq"; +import CodeEditor from "../CodeEditor/CodeEditor"; class Routes extends Component { componentDidUpdate() { @@ -47,6 +48,9 @@ class Routes extends Component { + + + {/* Sharing */} diff --git a/src/data/arduinoExamples.js b/src/data/arduinoExamples.js new file mode 100644 index 0000000..207c203 --- /dev/null +++ b/src/data/arduinoExamples.js @@ -0,0 +1,16 @@ +import * as Blockly from "blockly/core"; + +export const ArduinoExamples = () => { + return [ + { + name: "MCU Component Test", + description: "Test the different compoenents of the MCU", + code: '// senseBox:home WiFi is enabled by default!\n// If you have a senseBox:home Ethernet comment out line 5\n// and comment in line 4\n// Do not comment in both at the same time!\n//#define ENABLE_ETHERNET\n#define ENABLE_WIFI\n\n#include \n#include \n#ifdef ENABLE_WIFI\n#include \n#include \n#endif\n#ifdef ENABLE_ETHERNET\n#include \n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n/********WiFi User Settings********/\nconst char *ssid = ""; // your network SSID (name)\nconst char *pass = ""; // your network password\n/**********************************/\nchar server[] = "internet-test.testing.opensensemap.org";\n#ifdef ENABLE_WIFI\nint status = WL_IDLE_STATUS;\nWiFiClient client;\n#endif\n\n#ifdef ENABLE_ETHERNET\n/********Ethernet User Settings********/\n//Configure static IP setup (only needed if DHCP is disabled)\nbyte mac[] = {0xDE,0xAD,0xBE,0xEF,0xFE,0xED};\nIPAddress myIp(192, 168, 0, 42);\nIPAddress myDns(8, 8, 8, 8);\nIPAddress myGateway(192, 168, 0, 177);\nIPAddress mySubnet(255, 255, 255, 0);\n/**********************************/\nEthernetClient ethernetClient;\n#endif\n\n#define CMD_RESET (0x00)\n#define CMD_SEND (0x03)\n#define ECC_READ (0x02) // read command\n#define ECC_WRITE (0x12) // write command\n#define ECC_ZONE_CFG (0x00) // configuration zone\n#define ECC_ZONE_CNT_FLAG (0x80) // 1=32 bytes, 0=4 bytes\nvoid setup() {\n Serial.begin(9600);\n while(!Serial); // wait until serial is ready\n printMenu();\n // power on required ports\n senseBoxIO.powerI2C(false);\n senseBoxIO.powerXB1(false);\n senseBoxIO.powerUART(false);\n delay(250);\n senseBoxIO.powerI2C(true);\n senseBoxIO.powerXB1(true);\n senseBoxIO.powerUART(true);\n // init UART and I2C\n Serial1.begin(9600);\n Serial2.begin(9600);\n Wire.begin();\n}\nvoid loop() {\n char rx;\n if (Serial.available() > 0)\n {\n\n rx = Serial.read(); // get the character\n Serial.println("\\n\\n");\n // check if a number was received\n switch(rx)\n {\n case \'1\':\n check_uart_sensor();\n Serial.println("\\nI2C/Wire:");\n byte devices, address;\n devices = 0;\n for(address = 1; address < 127; address++ )\n {\n Wire.beginTransmission(address);\n byte error = Wire.endTransmission();\n\n if(error == 0)\n {\n devices++;\n Serial.print("Device found at 0x");\n delay(100);\n Serial.print(address, HEX);\n Serial.println();\n check_i2c_sensor(address);\n }\n else if(error==4)\n {\n Serial.print("Unknow error at 0x");\n delay(100);\n Serial.println(address, HEX);\n }\n }\n\n if(devices == 0) Serial.println("No devices found\\n");\n senseBoxIO.statusNone();\n delay(250);\n break;\n #ifdef ENABLE_WIFI\n case \'2\':\n connectionWiFiTest();\n Serial.println("");\n delay(250);\n break;\n #endif\n #ifdef ENABLE_ETHERNET\n case \'3\':\n connectionEthernetTest();\n Serial.println("");\n delay(250);\n break;\n #endif\n case \'4\':\n Serial.println("Security key:");\n getSecKey();\n Serial.println();\n delay(250);\n break;\n case \'5\':\n Serial.flush();\n NVIC_SystemReset();\n break;\n }\n Serial.flush();\n }\n}\nvoid printMenu()\n{\n Serial.println("senseBox MCU option menu\\nType one of the numbers in the input field above and hit \'Enter\'.");\n delay(100);\n Serial.println(" 1 - Find connected devices");\n #ifdef ENABLE_WIFI\n delay(100);\n Serial.println(" 2 - Test connection to openSenseMap (WiFi on XBee1)");\n #endif\n #ifdef ENABLE_ETHERNET\n delay(100);\n Serial.println(" 3 - Test connection to openSenseMap (Ethernet on XBee1)");\n #endif\n delay(100);\n Serial.println(" 4 - Get security key\\n");\n return;\n}\nvoid check_uart_sensor(){\n Serial.println("UART/Serial Port:");\n SDS011 sds1(Serial1);\n SDS011 sds2(Serial2);\n float pm10,pm25;\n int sds_error;\n sds_error = sds1.read(&pm25,&pm10);\n if (!sds_error)\n {\n Serial.println("SDS011 dust particle sensor found at serial port #1.");\n }\n else\n {\n sds_error = sds2.read(&pm25,&pm10);\n if (!sds_error)\n {\n Serial.println("SDS011 dust particle sensor found at serial port #2.");\n return;\n }\n }\n Serial.println("No device found.");\n}\nvoid check_i2c_sensor(byte address)\n{\n float t=0, h=0, p=0, a=0;\n unsigned int u=0;\n unsigned long l=0;\n Adafruit_BMP280 bmp280;\n Adafruit_BME280 bme280;\n Adafruit_BME680 bme680;\n Adafruit_HDC1000 hdc;\n if((address == 0) || (address > 127))\n {\n return;\n }\n switch(address)\n {\n case 0x29: //TSL45315\n Serial.println("--- TSL45315");\n Wire.beginTransmission(address);\n Wire.write(0x80|0x00); //control\n Wire.write(0x03);\n Wire.endTransmission();\n Wire.beginTransmission(address);\n Wire.write(0x80|0x01); //config\n Wire.write(0x02); //M=4 T=100ms\n Wire.endTransmission();\n delay(120);\n Wire.beginTransmission(address);\n Wire.write(0x80|0x04); //data low\n Wire.endTransmission();\n Wire.requestFrom((uint8_t)address, (uint8_t)2);\n delay(1);\n u |= (Wire.read()<<8);\n u |= (Wire.read()<<8);\n l = u * 4;\n Serial.print("Lux ");\n Serial.println(l, DEC);\n break;\n case 0x38: //VEML6070\n //case 0x39:\n Serial.println("--- VEML6070 (0x38+0x39)");\n Wire.beginTransmission(address);\n Wire.write((0x1<<2) | 0x02); //Integration Time 1\n Wire.endTransmission();\n delay(120);\n Wire.requestFrom((uint8_t)(address+1), (uint8_t)1); //MSB\n delay(1);\n u |= (Wire.read()<<8);\n Wire.requestFrom((uint8_t)(address+0), (uint8_t)1); //LSB\n delay(1);\n u |= (Wire.read()<<0);\n Serial.print("UV ");\n Serial.println(u, DEC);\n break;\n case 0x40: //HDC100X\n case 0x41:\n //case 0x42:\n case 0x43:\n Serial.println("--- HDC100X");\n hdc.begin(address);\n t = hdc.readTemperature();\n h = hdc.readHumidity();\n Serial.print("Temp ");\n Serial.print(t, DEC);\n Serial.println(" *C");\n Serial.print("Humi ");\n Serial.print(h, DEC);\n Serial.println(" %");\n break;\n case 0x76: //BMP280 or BME280 or BME680\n case 0x77:\n if(bmp280.begin(address) != 0)\n {\n Serial.println("--- BMP280");\n delay(100);\n t = bmp280.readTemperature();\n p = bmp280.readPressure();\n a = bmp280.readAltitude(1013.25); //1013.25 = sea level pressure\n }\n else if(bme280.begin(address) != 0)\n {\n Serial.println("--- BME280");\n delay(100);\n t = bme280.readTemperature();\n p = bme280.readPressure();\n a = bme280.readAltitude(1013.25); //1013.25 = sea level pressure\n h = bme280.readHumidity();\n }\n else if(bme680.begin(address) != 0)\n {\n Serial.println("--- BME680");\n delay(100);\n bme680.performReading();\n t = bme680.temperature;\n p = bme680.pressure;\n a = bme680.readAltitude(1013.25); //1013.25 = sea level pressure\n h = bme680.humidity;\n u = bme680.gas_resistance / 1000.0;\n }\n else\n {\n Wire.beginTransmission(address);\n Wire.write(0xD0); //chip id\n Wire.endTransmission();\n Wire.requestFrom(address, (byte)1);\n delay(1);\n u = Wire.read();\n if(u == 0x58) //BMP280\n {\n Serial.println("--- BMP280");\n }\n else if(u == 0x60) //BME280\n {\n Serial.println("--- BME280");\n }\n else if(u == 0x61) //BME680\n {\n Serial.println("--- BME680");\n }\n }\n Serial.print("Temp ");\n Serial.print(t, DEC);\n Serial.println(" *C");\n Serial.print("Pres ");\n Serial.print(p/100.0, DEC);\n Serial.println(" hPa");\n Serial.print("Alti ");\n Serial.print(a, DEC);\n Serial.println(" m");\n if(h != 0)\n {\n Serial.print("Humi ");\n Serial.print(h, DEC);\n Serial.println(" %");\n }\n if(u != 0)\n {\n Serial.print("Gas ");\n Serial.print(u, DEC);\n Serial.println(" kOhm");\n }\n break;\n case 0x42: //CAM-M8Q\n Serial.println("--- CAM-M8Q");\n break;\n case 0x50: //24LCxxx EEPROM\n Serial.println("--- 24LCxxx");\n break;\n case 0x60: //ATECCx08\n Serial.println("--- ATECCx08");\n break;\n case 0x68: //RV8523\n Serial.println("--- RV8523");\n break;\n }\n delay(250); //wait 250ms\n}\nvoid getSecKey()\n{\n Wire1.begin();\n // init ATECC\n write(CMD_RESET, 0x00); // reset\n delay(100); // wait 100ms\n // read config zone\n byte buf[64]; // buffer\n buf[0] = 5+2; // length: data + 2 crc bytes\n buf[1] = ECC_READ; // cmd\n buf[2] = ECC_ZONE_CFG|ECC_ZONE_CNT_FLAG; // param 1\n buf[3] = 0x00; // addr lsb\n buf[4] = 0x00; // addr msb\n //buf[5] = 0x00; // crc\n //buf[6] = 0x00; // crc\n calc_crc(buf, buf[0]-2, &buf[5]); // calc crc\n write(CMD_SEND, buf, buf[0]); // send cmd\n delay(10); // wait 10ms\n read(buf, sizeof(buf)); // read response\n Serial.print("0");\n Serial.print(buf[1], HEX); Serial.print(" ");\n Serial.print(buf[2], HEX); Serial.print(" ");\n Serial.print(buf[3], HEX); Serial.print(" ");\n Serial.print(buf[4], HEX); Serial.print(" ");\n Serial.print(buf[ 9], HEX); Serial.print(" ");\n Serial.print(buf[10], HEX); Serial.print(" ");\n Serial.print(buf[11], HEX); Serial.print(" ");\n Serial.print(buf[12], HEX); Serial.print(" ");\n Serial.print(buf[13], HEX); Serial.print(" ");\n Serial.println("");\n}\nvoid read(byte *data, byte max_len)\n{\n byte len;\n Wire1.requestFrom(I2C_ATECC, 1); // request length\n while(Wire1.available() == 0); // wait for data bytes\n len = Wire1.read();\n *data++ = len;\n if(len)\n {\n Wire1.requestFrom(I2C_ATECC, len); // request x bytes\n while(Wire1.available() == 0); // wait for data bytes\n delay(10); // wait 10ms\n for(byte i = 0; (i < len) && (i < max_len); i++)\n {\n *data++ = Wire1.read(); // read data byte\n }\n }\n}\nvoid write(byte reg, byte *data, byte len)\n{\n Wire1.beginTransmission(I2C_ATECC); // start transmission\n Wire1.write(reg); // write register byte\n for(; len != 0; len--)\n {\n Wire1.write(*data++); // write data byte\n }\n Wire1.endTransmission(); // stop transmission\n}\nvoid write(byte reg, byte data)\n{\n Wire1.beginTransmission(I2C_ATECC); // start transmission\n Wire1.write(reg); // write register byte\n Wire1.write(data); // write data byte\n Wire1.endTransmission(); // stop transmission\n}\nvoid calc_crc(byte *data, byte len, byte *crc)\n{\n uint8_t i, shift_reg, data_bit, crc_bit;\n uint16_t crc_reg = 0;\n uint16_t polynom = 0x8005;\n for(i = 0; i < len; i++)\n {\n for(shift_reg = 0x01; shift_reg > 0x00; shift_reg <<= 1)\n {\n data_bit = (data[i] & shift_reg) ? 1 : 0;\n crc_bit = crc_reg >> 15;\n crc_reg <<= 1;\n if(data_bit != crc_bit)\n {\n crc_reg ^= polynom;\n }\n }\n }\n crc[0] = (byte)(crc_reg & 0x00FF);\n crc[1] = (byte)(crc_reg >> 8);\n}\nvoid connectionWiFiTest(){\n #ifdef ENABLE_WIFI\n if (WiFi.status() == WL_NO_SHIELD)\n {\n Serial.println("WiFi bee not present");\n return;\n }\n Serial.println("Check WiFi firmware:");\n Serial.println("====================");\n // Print firmware version on the shield\n String fv = WiFi.firmwareVersion();\n String latestFv;\n Serial.print("Firmware version installed: ");\n Serial.println(fv);\n\n if (REV(GET_CHIPID()) >= REV_3A0) {\n // model B\n latestFv = WIFI_FIRMWARE_LATEST_MODEL_B;\n } else {\n // model A\n latestFv = WIFI_FIRMWARE_LATEST_MODEL_A;\n }\n\n // Print required firmware version\n Serial.print("Latest firmware version available : ");\n Serial.println(latestFv);\n\n // Check if the latest version is installed\n Serial.println();\n if (fv == latestFv || fv == "19.5.2") {\n Serial.println("Check result: PASSED");\n } else {\n Serial.println("Check result: NOT PASSED");\n Serial.println(" - The firmware version on the shield do not match the");\n Serial.println(" version required by the library, you may experience");\n Serial.println(" issues or failures.");\n Serial.println(" - Update the firmware at least to version 19.5.2");\n }\n\n Serial.println();\n Serial.println("Check internet connectivity:");\n Serial.println("============================");\n\n if (WiFi.status() != WL_CONNECTED) {\n Serial.print("Connecting to WiFi...");\n delay(1000); // wait 1s\n WiFi.begin(ssid, pass);\n delay(5000); // wait 5s\n }\n if (WiFi.status() == WL_CONNECTED) Serial.println("connected!");\n else\n {\n Serial.println("failed! Please check SSID and password.");\n return;\n }\n for (uint8_t timeout = 2; timeout != 0; timeout--)\n {\n Serial.print("Calling openSenseMap server...");\n if (client.connect(server, 80))\n {\n Serial.println("connected!");\n // Make a HTTP request:\n client.println("GET / HTTP/1.1");\n client.print("Host: ");\n client.println(server);\n client.println("Connection: close");\n client.println();\n }\n break;\n }\n if(client.connected())\n {\n // wait for server response\n Serial.println("Server response:\\n");\n while (!client.available())\n {\n delay(1);\n }\n // read server response\n while (client.available())\n {\n char c = client.read();\n Serial.write(c);\n }\n Serial.print("\\n");\n Serial.println("Disconnecting from server.");\n client.flush();\n client.stop();\n }else Serial.println("failed after 3 trys!");\n Serial.println("Disconnecting from WiFi.");\n WiFi.disconnect();\n #endif\n}\n\nvoid connectionEthernetTest() {\n #ifdef ENABLE_ETHERNET\n Ethernet.init(PIN_XB1_CS);\n Serial.println("Trying to initialize DHCP...");\n if (Ethernet.begin(mac) == 0) {\n Serial.println("Failed to configure Ethernet using DHCP");\n // start the Ethernet connection using a fixed IP address and DNS server:\n Serial.println("Trying Ethernet connection using a fixed IP address and DNS server");\n Ethernet.begin(mac, myIp, myDns, mySubnet);\n } else {\n // print your local IP address:\n Serial.println("DHCP is working.");\n Serial.print("My IP address: ");\n for (byte thisByte = 0; thisByte < 4; thisByte++) {\n // print the value of each byte of the IP address:\n Serial.print(Ethernet.localIP()[thisByte], DEC);\n Serial.print(".");\n }\n Serial.println();\n }\n for (uint8_t timeout = 2; timeout != 0; timeout--)\n {\n Serial.print("Calling openSenseMap server...");\n if (ethernetClient.connect(server, 80))\n {\n Serial.println("connected!");\n // Make a HTTP request:\n ethernetClient.println("GET / HTTP/1.1");\n ethernetClient.print("Host: ");\n ethernetClient.println(server);\n ethernetClient.println("Connection: close");\n ethernetClient.println();\n }\n break;\n }\n if(ethernetClient.connected())\n {\n // wait for server response\n Serial.println("Server response:\\n");\n while (!ethernetClient.available())\n {\n delay(1);\n }\n // read server response\n while (ethernetClient.available())\n {\n char c = ethernetClient.read();\n Serial.write(c);\n }\n Serial.print("\\n");\n Serial.println("Disconnecting from server.");\n ethernetClient.flush();\n ethernetClient.stop();\n }\n else Serial.println("failed after 3 trys!");\n #endif\n}', + }, + { + name: "ArduinoBearSSL", + description: "BearSSL is a TLS/SSL library for Arduino", + code: "", + }, + ]; +}; diff --git a/src/data/versions.js b/src/data/versions.js new file mode 100644 index 0000000..d5d2e2c --- /dev/null +++ b/src/data/versions.js @@ -0,0 +1,104 @@ +import * as Blockly from "blockly/core"; + +export const LibraryVersions = () => { + return [ + { + version: "1.4.2", + library: "sensebox/SenseBoxMCU-Lib", + link: "https://github.com/sensebox/SenseBoxMCU-Lib", + }, + { + version: "1.0.12", + library: "sparkfun/SparkFun_SCD30_Arduino_Library", + }, + { version: "1.2.3", library: "adafruit/Adafruit-GFX-Library" }, + { + version: "2.1.2", + library: "adafruit/Adafruit_BME280_Library", + }, + { + version: "2.1.0", + library: "adafruit/Adafruit_BMP280_Library", + }, + { + version: "1.1.1", + library: "adafruit/Adafruit_BME680", + }, + { + version: "2.0.1", + library: "adafruit/Adafruit_BMP3XX", + }, + { + version: "2.0.0", + library: "adafruit/Adafruit_HDC1000_Library", + }, + { + version: "1.7.1", + library: "adafruit/Adafruit_BusIO", + }, + { + version: "1.0.6", + library: "adafruit/Adafruit_NeoPixel", + }, + { + version: "1.1.2", + library: "adafruit/Adafruit_SSD1306", + }, + { + version: "1.0.2", + library: "adafruit/Adafruit_Sensor", + }, + { + version: "3.8.0", + library: "milesburton/Arduino-Temperature-Control-Library", + }, + { + version: "1.5.0", + library: "arduino-libraries/ArduinoBearSSL", + }, + { + version: "1.3.4", + library: "arduino-libraries/ArduinoECCX08", + }, + { + version: "2.0.0", + library: "arduino-libraries/ArduinoECCX08", //todo + }, + { + version: "0.7.1", + library: "cmaglie/FlashStorage", + }, + { + version: "1.5.1", + library: "matthijskooijman/arduino-lmic", + }, + { + version: "3.0.1", + library: "thesolarnomad/lora-serialization ", + }, + { + version: "todo", + library: "TSL45xxx", + }, + { + version: "2.3.4", + library: "teensy/td_libs_OneWire.html", + }, + { + version: "1.0.0", + library: "watterott/Arduino-Libs/tree/master/RV8523", + }, + { + version: "1.0.0", + library: "sensebox/SDS011-select-serial ", + }, + { + version: "1.0.0", + library: "Lucas-Steinmann/SSD1306-Plot-Library", + }, + { + version: "1.0.0", + library: "senseBoxIO", + }, + ]; +}; diff --git a/yarn.lock b/yarn.lock index 7ed0fee..f31665f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1542,6 +1542,21 @@ "prop-types" "^15.7.2" "react-is" "^16.8.0" +"@monaco-editor/loader@^1.2.0": + "integrity" "sha512-cJVCG/T/KxXgzYnjKqyAgsKDbH9mGLjcXxN6AmwumBwa2rVFkwvGcUj1RJtD0ko4XqLqJxwqsN/Z/KURB5f1OQ==" + "resolved" "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "state-local" "^1.0.6" + +"@monaco-editor/react@^4.3.1": + "integrity" "sha512-f+0BK1PP/W5I50hHHmwf11+Ea92E5H1VZXs+wvKplWUWOfyMa1VVwqkJrXjRvbcqHL+XdIGYWhWNdi4McEvnZg==" + "resolved" "https://registry.npmjs.org/@monaco-editor/react/-/react-4.3.1.tgz" + "version" "4.3.1" + dependencies: + "@monaco-editor/loader" "^1.2.0" + "prop-types" "^15.7.2" + "@nodelib/fs.scandir@2.1.4": "integrity" "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==" "resolved" "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz" @@ -8224,6 +8239,11 @@ "resolved" "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz" "version" "2.29.0" +"monaco-editor@>= 0.21.0 < 1", "monaco-editor@>= 0.25.0 < 1": + "integrity" "sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q==" + "resolved" "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.31.1.tgz" + "version" "0.31.1" + "move-concurrently@^1.0.1": "integrity" "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=" "resolved" "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz" @@ -10032,7 +10052,7 @@ "strip-ansi" "6.0.0" "text-table" "0.2.0" -"react-dom@^17.0.0", "react-dom@^17.0.2": +"react-dom@^16.8.0 || ^17.0.0", "react-dom@^17.0.0", "react-dom@^17.0.2": "integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==" "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz" "version" "17.0.2" @@ -10211,7 +10231,7 @@ "loose-envify" "^1.4.0" "prop-types" "^15.6.2" -"react@^16.8.3 || ^17", "react@^17.0.0", "react@^17.0.2", "react@>= 16", "react@17.0.2": +"react@^16.8.0 || ^17.0.0", "react@^16.8.3 || ^17", "react@^17.0.0", "react@^17.0.2", "react@>= 16", "react@17.0.2": "integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==" "resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz" "version" "17.0.2" @@ -11408,6 +11428,11 @@ "resolved" "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz" "version" "1.2.0" +"state-local@^1.0.6": + "integrity" "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==" + "resolved" "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz" + "version" "1.0.7" + "static-extend@^0.1.1": "integrity" "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=" "resolved" "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz"