diff --git a/GUI/server/odrive_server.py b/GUI/server/odrive_server.py index 0ee37692..7501d7fa 100644 --- a/GUI/server/odrive_server.py +++ b/GUI/server/odrive_server.py @@ -58,8 +58,12 @@ def discovered_device(device): while globals()['inUse']: time.sleep(0.1) globals()['odrives'][odrive_name] = device + globals()['odrives_status'][odrive_name] = True print("Found " + str(serial_number)) print("odrive list: " + str([key for key in globals()['odrives'].keys()])) + # tell GUI the status of known ODrives (previously connected and then disconnected ODrives will be "False") + socketio.emit('odrives-status', json.dumps(globals()['odrives_status'])) + # triggers a getODrives socketio message socketio.emit('odrive-found') def start_discovery(): @@ -68,9 +72,12 @@ def start_discovery(): shutdown = fibre.Event() fibre.find_all("usb", None, discovered_device, shutdown, shutdown, log) -def handle_disconnect(): +def handle_disconnect(odrive_name): print("lost odrive") - #socketio.emit('odrive-disconnected') + globals()['odrives_status'][odrive_name] = False + # emit the whole list of odrive statuses + # in the GUI, mark and use status as ODrive state. + socketio.emit('odrives-status', json.dumps(globals()['odrives_status'])) @socketio.on('findODrives') def getODrives(message): @@ -115,8 +122,9 @@ def get_odrives(data): odriveDict = {} #for (index, odrv) in enumerate(globals()['odrives']): # odriveDict["odrive" + str(index)] = dictFromRO(odrv) - for key in globals()['odrives'].keys(): - odriveDict[key] = dictFromRO(globals()['odrives'][key]) + for key in globals()['odrives_status'].keys(): + if globals()['odrives_status'][key] == True: + odriveDict[key] = dictFromRO(globals()['odrives'][key]) globals()['inUse'] = False emit('odrives', json.dumps(odriveDict)) @@ -126,10 +134,11 @@ def get_property(message): # will be {"path": "odriveX.axisY.blah.blah"} while globals()['inUse']: time.sleep(0.1) - globals()['inUse'] = True - val = getVal(globals()['odrives'], message["path"].split('.')) - globals()['inUse'] = False - emit('ODriveProperty', json.dumps({"path": message["path"], "val": val})) + if globals()['odrives_status'][message["path"].split('.')[0]]: + globals()['inUse'] = True + val = getVal(globals()['odrives'], message["path"].split('.')) + globals()['inUse'] = False + emit('ODriveProperty', json.dumps({"path": message["path"], "val": val})) @socketio.on('setProperty') def set_property(message): @@ -194,7 +203,7 @@ def postVal(odrives, keyList, value, argType): else: pass # dont support that type yet except fibre.protocol.ChannelBrokenException: - handle_disconnect() + handle_disconnect(odrv) except: print("exception in postVal") @@ -210,7 +219,7 @@ def getVal(odrives, keyList): else: return RO.get_value() except fibre.protocol.ChannelBrokenException: - handle_disconnect() + handle_disconnect(odrv) except: print("exception in getVal") return 0 @@ -235,7 +244,7 @@ def callFunc(odrives, keyList): if isinstance(RO, fibre.remote_object.RemoteFunction): RO.__call__() except fibre.protocol.ChannelBrokenException: - handle_disconnect() + handle_disconnect(odrv) except: print("fcn call failed") @@ -252,7 +261,11 @@ if __name__ == "__main__": import odrive.utils # for dump_errors() import fibre + # global for holding references to all connected odrives globals()['odrives'] = {} + # global dict {'odriveX': True/False} where True/False reflects status of connection + # on handle_disconnect, set it to False. On connection, set it to True + globals()['odrives_status'] = {} globals()['discovered_devices'] = [] # spinlock globals()['inUse'] = False diff --git a/GUI/src/App.vue b/GUI/src/App.vue index 2c9f52e6..fd64070a 100644 --- a/GUI/src/App.vue +++ b/GUI/src/App.vue @@ -56,9 +56,6 @@ :axis="axis.name" :odrives="odrives" > - @@ -129,22 +126,6 @@ export default { currentDash: function () { return this.$store.state.currentDash; }, - ODriveConnected: function () { - // if server and odrive disconnected, disconnected - // if server connected and odrive disco, connecting - // if server and odrive connected, connected - let ret; - if (this.$store.state.serverConnected && this.$store.state.ODriveConnected) { - ret = "connected"; - } - else if (this.$store.state.serverConnected && !this.$store.state.ODriveConnected) { - ret = "connecting..."; - } - else { - ret = "disconnected"; - } - return ret; - }, samplingText: function () { let ret; if (this.$store.state.sampling) { diff --git a/GUI/src/components/Axis.vue b/GUI/src/components/Axis.vue index 2ee3503a..8d0806ba 100644 --- a/GUI/src/components/Axis.vue +++ b/GUI/src/components/Axis.vue @@ -2,7 +2,7 @@
{{ axis }}
@@ -110,6 +110,9 @@ export default { }; }, computed: { + connected() { + return this.$store.state.ODrivesConnected[this.axis.split('.')[0]]; + }, axisErrorMsg() { let retMsg = "none"; let errCode = this.axisErr; @@ -229,14 +232,18 @@ export default { created() { // set up timeout loop for grabbing axis error values let update = () => { - fetchParam(this.axis + ".error"); - fetchParam(this.axis + '.motor.error'); - fetchParam(this.axis + '.controller.error'); - fetchParam(this.axis + '.encoder.error'); - this.axisErr = getVal(this.axis + '.error'); - this.motorErr = getVal(this.axis + '.motor.error'); - this.controllerErr = getVal(this.axis + '.controller.error'); - this.encoderErr = getVal(this.axis + '.encoder.error'); + // Do we have an active connection to the ODrive that contains this axis? + if (this.$store.state.ODrivesConnected[this.axis.split('.')[0]]) { + fetchParam(this.axis + ".error"); + fetchParam(this.axis + '.motor.error'); + fetchParam(this.axis + '.controller.error'); + fetchParam(this.axis + '.encoder.error'); + this.axisErr = getVal(this.axis + '.error'); + this.motorErr = getVal(this.axis + '.motor.error'); + this.controllerErr = getVal(this.axis + '.controller.error'); + this.encoderErr = getVal(this.axis + '.encoder.error'); + } + // ODrive not connected setTimeout(update, 1000); } update(); @@ -270,4 +277,8 @@ export default { color: black; margin-left: 0px; } + +.inactive { + color: grey; +} \ No newline at end of file diff --git a/GUI/src/components/actions/Action.vue b/GUI/src/components/actions/Action.vue index ce896c31..d78948b6 100644 --- a/GUI/src/components/actions/Action.vue +++ b/GUI/src/components/actions/Action.vue @@ -40,7 +40,7 @@ export default { methods: { newVal: function (e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.value = val; console.log("input = " + e.target.value + ", val = " + this.value); this.$store.commit("setActionVal", {dashID: this.dashID, actionID: this.id, val: this.value}); diff --git a/GUI/src/components/controls/CtrlNumeric.vue b/GUI/src/components/controls/CtrlNumeric.vue index 752dbce6..2e3af0a6 100644 --- a/GUI/src/components/controls/CtrlNumeric.vue +++ b/GUI/src/components/controls/CtrlNumeric.vue @@ -47,8 +47,9 @@ export default { putVal: function (e) { let keys = this.path.split('.'); keys.shift(); + console.log("input recieved: " + e.target.value); let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { putVal(keys.join('.'), val); } }, diff --git a/GUI/src/components/wizard/choices/wizardBrake.vue b/GUI/src/components/wizard/choices/wizardBrake.vue index caef2057..42a69e73 100644 --- a/GUI/src/components/wizard/choices/wizardBrake.vue +++ b/GUI/src/components/wizard/choices/wizardBrake.vue @@ -37,7 +37,7 @@ export default { setBR(e) { console.log("from setBR " + e.target.value); let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.brake_resistance = val; let configStub = undefined; configStub = { diff --git a/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue b/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue index 6395f921..2c296abd 100644 --- a/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue +++ b/GUI/src/components/wizard/choices/wizardEncoderIncremental.vue @@ -26,7 +26,7 @@ export default { methods: { setCPR(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.cpr = val; let configStub = undefined; if (this.data.axis == "axis0") { diff --git a/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue b/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue index 79baa12a..85357d41 100644 --- a/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue +++ b/GUI/src/components/wizard/choices/wizardEncoderIncrementalIndex.vue @@ -27,7 +27,7 @@ export default { methods: { setCPR(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.cpr = val; let configStub = undefined; if (this.data.axis == "axis0") { diff --git a/GUI/src/components/wizard/choices/wizardMisc.vue b/GUI/src/components/wizard/choices/wizardMisc.vue index 9aa8f39f..f5aaa484 100644 --- a/GUI/src/components/wizard/choices/wizardMisc.vue +++ b/GUI/src/components/wizard/choices/wizardMisc.vue @@ -100,7 +100,7 @@ export default { }, setVelocityLimit(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.vel_limit = parseFloat(e.target.value); this.vel_set = true; this.sendConfig(); @@ -108,7 +108,7 @@ export default { }, setCurrentLimit(e) { let val = parseMath(e.target.value); - if (val != false) { + if (val !== false) { this.current_lim = parseFloat(e.target.value); this.current_set = true; this.sendConfig(); diff --git a/GUI/src/lib/odrive_utils.js b/GUI/src/lib/odrive_utils.js index 8f1993e2..e022425a 100644 --- a/GUI/src/lib/odrive_utils.js +++ b/GUI/src/lib/odrive_utils.js @@ -6,11 +6,17 @@ import * as socketio from "../comms/socketio.js"; // given a path like "odrive0.axis0.config.blah", return the value export function getParam(path) { let keys = path.split('.'); - let odriveObj = store.state.odrives; - for (const key of keys) { - odriveObj = odriveObj[key]; + if (store.state.ODrivesConnected[keys[0]]) { + let odriveObj = store.state.odrives; + for (const key of keys) { + odriveObj = odriveObj[key]; + } + return odriveObj; + } + else { + console.log("getParam for " + path + " is for disconnected ODrive"); + return undefined; } - return odriveObj; } // wrapper for val field @@ -51,10 +57,15 @@ export function parseMath(inString) { export function putVal(path, value) { console.log("path: " + path + ", val: " + value + ", type: " + typeof value); - socketio.sendEvent({ - type: "setProperty", - data: {path: path, val: value, type: typeof value} - }) + if (store.state.ODrivesConnected[path.split('.')[0]]) { + socketio.sendEvent({ + type: "setProperty", + data: {path: path, val: value, type: typeof value} + }); + } + else { + console.log("requesting " + path + " from disconnected odrive") + } } // path is path to function, args is list of parameters diff --git a/GUI/src/store.js b/GUI/src/store.js index 21b10b97..16be7562 100644 --- a/GUI/src/store.js +++ b/GUI/src/store.js @@ -21,7 +21,7 @@ export default new Vuex.Store({ axes: Array, odriveServerAddress: String, serverConnected: Boolean, - ODriveConnected: false, + ODrivesConnected: Object, serverOutput: [], dashboards: [ { @@ -95,6 +95,13 @@ export default new Vuex.Store({ state.odriveConfigs['writeAble'] = payload.writeAble; state.odriveConfigs['writeAbleNumeric'] = payload.writeAbleNumeric; }, + setODrivesStatus(state, obj) { + // obj is {"odriveX": true/false} + for (const odrive of Object.keys(obj)){ + state.ODrivesConnected[odrive] = obj[odrive]; + console.log(state.ODrivesConnected); + } + }, setAxes(state, axes) { state.axes = axes; }, @@ -163,9 +170,6 @@ export default new Vuex.Store({ setServerStatus(state, val) { state.serverConnected = val; }, - setODriveConnected(state, val) { - state.ODriveConnected = val; - }, removeCtrlFromDash(state, obj) { // obj is {dash: dashID, path: control path} for (const dash of state.dashboards) { @@ -325,7 +329,6 @@ export default new Vuex.Store({ type: "odrive-found", callback: () => { console.log("odrive-found recieved from server"); - context.commit("setODriveConnected", true); context.dispatch("getOdrives"); } }) @@ -370,15 +373,21 @@ export default new Vuex.Store({ }); socketio.addEventListener({ type: "odrive-disconnected", - callback: () => { - console.log("odrive disconnected"); - context.commit("setODriveConnected", false); - console.log("restarting server..."); - window.ipcRenderer.send('kill-server'); - window.ipcRenderer.send('start-server'); - context.dispatch('setServerAddress', context.state.odriveServerAddress); + callback: (odrive_name) => { + console.log(odrive_name + " disconnected"); + //console.log("restarting server..."); + //window.ipcRenderer.send('kill-server'); + //window.ipcRenderer.send('start-server'); + //context.dispatch('setServerAddress', context.state.odriveServerAddress); } - }) + }); + socketio.addEventListener({ + type: "odrives-status", + callback: (odrives_status) => { + console.log("From odrives-status msg " + odrives_status); + context.commit('setODrivesStatus', JSON.parse(odrives_status)); + } + }); } } }) \ No newline at end of file