diff --git a/README.md b/README.md index 4cad8a00..964aa7cc 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ rclnodejs.init().then(() => { - [API Documentation](#api-documentation) - [Using TypeScript](#using-rclnodejs-with-typescript) - [Examples](https://github.com/RobotWebTools/rclnodejs/tree/develop/example) +- [Electron demo](https://github.com/RobotWebTools/rclnodejs/tree/develop/electron_demo) - [Efficient Usage Tips](./docs/EFFICIENCY.md) - [FAQ and Known Issues](./docs/FAQ.md) - [Building from Scratch](./docs/BUILDING.md) diff --git a/electron_demo/README.md b/electron_demo/README.md new file mode 100644 index 00000000..0f2c0517 --- /dev/null +++ b/electron_demo/README.md @@ -0,0 +1,54 @@ +# Rclnodejs Electron demo + +## Introduction + +This is a minimal rclnodejs demo using Electron. More information about Electron, please check with [Electron documentation](https://electronjs.org/docs/latest/tutorial/quick-start). + +The demo includes the following files: + +- `package.json` - Points to the app's main file and lists its details and dependencies. +- `main.js` - Introduces the `rclnodejs` native module, starts the app and creates a browser window to render HTML. This is the app's **main process**. +- `index.html` - Includes a text editor where you can input the the topic to be published. This is the app's **renderer process**. +- `renderer.js` - Communicate with main process to publish a topic and get it through a subscription. + +## To run the demo + +Before starting, please ensure you have installed [nodejs](https://nodejs.org/en). + +1. Clone this repository. + +```bash +git clone https://github.com/RobotWebTools/rclnodejs.git +``` + +2. Go into the demo. +```bash +cd rclnodejs/electron_demo +``` + +3. [SOURCE THE ROS 2 SETUP FILE](https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html#source-the-setup-files) + +4. Install dependencies +```bash +npm install +``` + +5. Rebuild rclnodejs for Electron +```bash +# Every time you run "npm install", run this: +./node_modules/.bin/electron-rebuild +``` + +6. Run the app +``` +npm start +``` + +If it works, you can see the demo as: +![demo screenshot](./electron-demo.gif) + +## Resources for Learning Electron + +- [electronjs.org/docs](https://electronjs.org/docs) - all of Electron's documentation. +- [Native Node Modules](https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules) - Use a native node module. + diff --git a/electron_demo/electron-demo.gif b/electron_demo/electron-demo.gif new file mode 100644 index 00000000..3943fcde Binary files /dev/null and b/electron_demo/electron-demo.gif differ diff --git a/electron_demo/index.html b/electron_demo/index.html new file mode 100644 index 00000000..ed095487 --- /dev/null +++ b/electron_demo/index.html @@ -0,0 +1,25 @@ + + + + + + + RCLNODEJS Electron Demo + + + +
+
+
+ + +
+
+ Received topic: + +
+ + + + diff --git a/electron_demo/main.js b/electron_demo/main.js new file mode 100644 index 00000000..ab147435 --- /dev/null +++ b/electron_demo/main.js @@ -0,0 +1,66 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const { app, BrowserWindow } = require('electron') +let rclnodejs = require("rclnodejs"); +const { ipcMain } = require('electron'); + +function createWindow() { + // Create the browser window. + const mainWindow = new BrowserWindow({ + width: 800, + height: 600, + webPreferences: { + // Add the following two lines in order to use require() in renderer, see details + // https://stackoverflow.com/questions/44391448/electron-require-is-not-defined + nodeIntegration: true, + contextIsolation: false, + } + }); + + mainWindow.loadFile('index.html'); +} + +// This method will be called when Electron has finished +// initialization and is ready to create browser windows. +// Some APIs can only be used after this event occurs. +app.whenReady().then(() => { + createWindow(); + rclnodejs.init().then(() => { + let sender = null; + const node = rclnodejs.createNode('publisher_example_node'); + node.createSubscription('std_msgs/msg/String', 'topic', (msg) => { + if (sender) { + sender.send('topic-received', msg.data); + } + }); + const publisher = node.createPublisher('std_msgs/msg/String', 'topic'); + ipcMain.on('publish-topic', (event, topic) => { + publisher.publish(topic); + sender = event.sender; + }); + rclnodejs.spin(node); + }); + + app.on('activate', function () { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (BrowserWindow.getAllWindows().length === 0) createWindow(); + }); +}); + +// Quit when all windows are closed, except on macOS. There, it's common +// for applications and their menu bar to stay active until the user quits +// explicitly with Cmd + Q. +app.on('window-all-closed', function () { + if (process.platform !== 'darwin') app.quit() +}); diff --git a/electron_demo/package.json b/electron_demo/package.json new file mode 100644 index 00000000..27b63ff4 --- /dev/null +++ b/electron_demo/package.json @@ -0,0 +1,22 @@ +{ + "name": "rclnodejs-electron-demo", + "version": "1.0.0", + "description": "A minimal rclnodejs Electron application", + "main": "main.js", + "scripts": { + "start": "electron ." + }, + "keywords": [ + "Electron", + "rclnodejs", + "demo" + ], + "license": "Apache", + "dependencies": { + "rclnodejs": "^0.27.4" + }, + "devDependencies": { + "@electron/rebuild": "^3.6.0", + "electron": "^31.0.0" + } +} diff --git a/electron_demo/renderer.js b/electron_demo/renderer.js new file mode 100644 index 00000000..10933271 --- /dev/null +++ b/electron_demo/renderer.js @@ -0,0 +1,22 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const { ipcRenderer } = require('electron'); + +ipcRenderer.on('topic-received', function (event, response) { + document.getElementById('received-topic').innerText = response; +}); + +document.getElementById('publish-topic').addEventListener('click', () => { + const topic = document.getElementById('topic-input').value; + ipcRenderer.send('publish-topic', topic); +});