diff --git a/GUI/server/odrive_server.py b/GUI/server/odrive_server.py index 2261e240..5d55c05c 100644 --- a/GUI/server/odrive_server.py +++ b/GUI/server/odrive_server.py @@ -76,8 +76,6 @@ def home(): @app.route('/api/odrives', methods=["GET"]) def api_odrives(): - print(len(globals()['odrives'])) - print("inUse = " + str(globals()['inUse'])) # spinlock while globals()['inUse']: time.sleep(0.1) @@ -189,7 +187,7 @@ def getSampledData(vars): samples = {} for path in vars["paths"]: keys = path.split('.') - samples[path] = getVal(odrives, keys) + samples[path] = getVal(globals()['odrives'], keys) return samples @@ -208,8 +206,10 @@ def callFunc(odrives, keyList): print("fcn call failed") if __name__ == "__main__": - print("args from python:") - print(sys.argv[1:]) + # sleep to allow time for background.js to register event callbacks for stdout,stderr + time.sleep(3) + print("args from python: " + str(sys.argv[1:0])) + #print(sys.argv[1:]) # try to import based on command line arguments or config file for optPath in sys.argv[1:]: diff --git a/GUI/src/App.vue b/GUI/src/App.vue index 711ad5e1..eb6b8edf 100644 --- a/GUI/src/App.vue +++ b/GUI/src/App.vue @@ -5,8 +5,10 @@ + :class="[{ active: sampling === true }]" + > + start sampling + + > + X + {{ dash.name }} @@ -47,7 +58,12 @@ @@ -56,12 +72,11 @@ import Start from "./views/Start.vue"; import Dashboard from "./views/Dashboard.vue"; import Axis from "./components/Axis.vue"; -import Wizard from "./views/Wizard.vue" +import Wizard from "./views/Wizard.vue"; import * as socketio from "./comms/socketio"; import { saveAs } from "file-saver"; import { v4 as uuidv4 } from "uuid"; - -//let propSamplePeriod = 100; //sampling period for properties in ms +import { ipcRenderer } from "electron"; export default { name: "App", @@ -119,10 +134,10 @@ export default { }, currentDash: function () { return this.$store.state.currentDash; - } + }, }, methods: { - changeDash(dashName){ + changeDash(dashName) { console.log(dashName); this.$store.commit("setDash", dashName); }, @@ -229,6 +244,15 @@ export default { this.$store.dispatch("setServerAddress", "http://127.0.0.1:5000"); // connect to socketio on server for sampled data this.updateOdrives(); + // setup callbacks for ipcRenderer + ipcRenderer.on('server-stdout', (event, arg) => { + //console.log("SERVER STDOUT: " + arg); // prints "pong" + this.$store.commit('logServerMessage', arg); + }); + ipcRenderer.on('server-stderr', (event, arg) => { + //console.log("SERVER STDERR: " + arg); // prints "pong" + this.$store.commit('logServerMessage', arg); + }); }, }; diff --git a/GUI/src/background.js b/GUI/src/background.js index c62ba64a..dfe3c57e 100644 --- a/GUI/src/background.js +++ b/GUI/src/background.js @@ -1,6 +1,6 @@ 'use strict' -import { app, protocol, BrowserWindow } from 'electron' +import { app, protocol, BrowserWindow, ipcMain } from 'electron' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer' const isDevelopment = process.env.NODE_ENV !== 'production' @@ -38,28 +38,7 @@ function getPyCmd() { } function createWindow() { - // Spawn the python server - let scriptFilename = path.join(app.getAppPath(), '../server', 'odrive_server.py'); - const args = process.argv; - let effectiveCommand = []; - effectiveCommand.push(scriptFilename); - if (app.isPackaged === true) { - for (const arg of args.slice(1)) { - effectiveCommand.push(arg); - } - } - else { - for (const arg of args.slice(2)) { - effectiveCommand.push(arg); - } - } - var python = spawn(getPyCmd(), effectiveCommand); - python.stdout.on('data',function(data) { - console.log(data.toString('utf8')); - }); - python.stderr.on('data',function(data) { - console.log(data.toString('utf8')); - }); + // Create the browser window. win = new BrowserWindow({ width: 800, @@ -67,7 +46,8 @@ function createWindow() { webPreferences: { // Use pluginOptions.nodeIntegration, leave this alone // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info - nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION + nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, + //preload: path.join(__dirname, 'preload.js') }, icon: path.join(__static, 'icon.png') }) @@ -124,6 +104,30 @@ app.on('ready', async () => { } } createWindow() + // Spawn the python server + let scriptFilename = path.join(app.getAppPath(), '../server', 'odrive_server.py'); + const args = process.argv; + let effectiveCommand = []; + effectiveCommand.push(scriptFilename); + if (app.isPackaged === true) { + for (const arg of args.slice(1)) { + effectiveCommand.push(arg); + } + } + else { + for (const arg of args.slice(2)) { + effectiveCommand.push(arg); + } + } + var python = spawn(getPyCmd(), effectiveCommand); + python.stdout.on('data',function(data) { + console.log(data.toString('utf8')); + win.webContents.send('server-stdout', String(data.toString('utf8'))); + }); + python.stderr.on('data',function(data) { + console.log(data.toString('utf8')); + win.webContents.send('server-stderr', String(data.toString('utf8'))); + }); }) // Exit cleanly on request from parent process in development mode. diff --git a/GUI/src/main.js b/GUI/src/main.js index 535fd873..4c313025 100644 --- a/GUI/src/main.js +++ b/GUI/src/main.js @@ -4,7 +4,6 @@ import store from './store' import Tooltip from 'vue-directive-tooltip'; import 'vue-directive-tooltip/dist/vueDirectiveTooltip.css'; import 'typeface-roboto/index.css'; - Vue.config.productionTip = false Vue.use(Tooltip); diff --git a/GUI/src/store.js b/GUI/src/store.js index 4704f994..78a0cae4 100644 --- a/GUI/src/store.js +++ b/GUI/src/store.js @@ -6,6 +6,9 @@ const axios = require('axios'); import * as socketio from "./comms/socketio"; //import { v4 as uuidv4 } from "uuid"; + + + Vue.use(Vuex); export default new Vuex.Store({ @@ -16,6 +19,7 @@ export default new Vuex.Store({ axes: Array, odriveServerAddress: String, serverConnected: Boolean, + serverOutput: [], dashboards: [ { name: "Start", @@ -147,6 +151,14 @@ export default new Vuex.Store({ } state.newData = true; }, + logServerMessage(state, payload) { + // payload is string + state.serverOutput.push(payload); + // cut off to 1000 lines + if (state.serverOutput.length > 1000) { + state.serverOutput.splice(0,1); + } + }, setServerStatus(state, val) { state.serverConnected = val; }, diff --git a/GUI/src/views/Start.vue b/GUI/src/views/Start.vue index 99791a3e..1de0dfbd 100644 --- a/GUI/src/views/Start.vue +++ b/GUI/src/views/Start.vue @@ -9,6 +9,10 @@
+ +
+
{{msg}}
+
@@ -18,6 +22,11 @@ export default { name: 'Home', components: { }, + data() { + return { + showServerMessages: false, + } + }, computed: { connected() { return this.$store.state.serverConnected == true; @@ -27,6 +36,15 @@ export default { }, serverAddress() { return this.$store.state.odriveServerAddress; + }, + serverMessages() { + if (this.$store.state.serverOutput.length >= 10) { + let len = this.$store.state.serverOutput.length; + return this.$store.state.serverOutput.slice(len-10,len); + } + else { + return this.$store.state.serverOutput; + } } }, methods: { @@ -86,4 +104,18 @@ input:focus { .notConnected { border-bottom: 1px solid red; } + +.show-msg-button { + border: none; + background-color: var(--bg-color); + margin-top: 0.5rem; +} + +.server-msgs { + margin-top: 2rem; +} + +.server-msg { + font-family: "Roboto Mono", monospace; +} diff --git a/GUI/vue.config.js b/GUI/vue.config.js index 4c64b663..f275add5 100644 --- a/GUI/vue.config.js +++ b/GUI/vue.config.js @@ -3,6 +3,8 @@ module.exports = { pluginOptions: { electronBuilder: { + //preload: 'src/preload.js', + nodeIntegration: true, builderOptions: { "productName": "ODriveGUI", "asar": false,