From 39dbf0502abf100bcc9696ee56e9753bbac52c12 Mon Sep 17 00:00:00 2001 From: Ruben van de Ven Date: Sat, 8 Jun 2019 16:10:46 +0200 Subject: [PATCH] Fix a bug that the story strand 'end-finder' loops infinite, load saved state now uses the light/position id rather than device id, passing a message can trigger the light, and status changes provide cleaner logs --- hugvey/central_command.py | 24 +++++++++++++----------- hugvey/story.py | 24 +++++++++++++++--------- www/js/hugvey_console.js | 32 +++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/hugvey/central_command.py b/hugvey/central_command.py index 2491257..8866b10 100644 --- a/hugvey/central_command.py +++ b/hugvey/central_command.py @@ -128,7 +128,7 @@ class CentralCommand(object): # status['counts'] = {t: len(a) for t, a in status['history'].items() if t != 'directions' } status['counts'] = {} if not hv.story else hv.story.getLogCounts() status['duration'] = 0 if not hv.story else hv.story.timer.getElapsed() - status['has_state'] = Story.hugveyHasSavedState(hv.id) + status['has_state'] = Story.hugveyHasSavedState(hv.lightId) status['variables'] = {} if not isSelected or not hv.story else hv.story.variableValues return status @@ -456,7 +456,6 @@ class HugveyState(object): self.setLightStatus(lightOn) self.eventLogger.info(f"status: {self.status}") - def config(self, hostname, ip): self.ip = ip self.hostname = hostname @@ -607,8 +606,9 @@ class HugveyState(object): if self.google: self.google.setLanguage(language_code) - def pause(self): - self.logger.info('Pause') + def pause(self, log = True): + if log: + self.logger.info('Pause') if self.google: self.google.pause() if self.story: @@ -616,9 +616,10 @@ class HugveyState(object): self.isRunning.clear() self.setStatus(self.STATE_PAUSE) - def resume(self): + def resume(self, log = True): """Start playing without reset, also used to play from a saved state""" - self.logger.info('Resume') + if log: + self.logger.info('Resume') if self.google: self.google.resume() if self.story: @@ -629,11 +630,11 @@ class HugveyState(object): def restart(self): """Start playing with reset""" self.logger.info('Restart') - if Story.hugveyHasSavedState(self.id): - Story.clearSavedState(self.id) + if Story.hugveyHasSavedState(self.lightId): + Story.clearSavedState(self.lightId) if self.story: self.story.stop() - self.resume() + self.resume(log=False) def block(self): """Block a hugvey""" @@ -648,7 +649,8 @@ class HugveyState(object): def available(self): """Put in available mode""" self.logger.info('Finish/Await') - self.pause() +# TODO: Toggle running if config says so, but turn light on + self.pause(log=False) self.setStatus(self.STATE_AVAILABLE) def setLightStatus(self, on): @@ -666,7 +668,7 @@ class HugveyState(object): def gone(self): '''Status to 'gone' as in, shutdown/crashed/whatever ''' - self.pause() + self.pause(log=False) if self.story: self.story.stop() diff --git a/hugvey/story.py b/hugvey/story.py index e719021..b5dddeb 100644 --- a/hugvey/story.py +++ b/hugvey/story.py @@ -71,6 +71,7 @@ class Message(object): self.parseForVariables() self.uuid = None # Have a unique id each time the message is played back. self.color = None + self.lightChange = None def __getstate__(self): # Copy the object's state from self.__dict__ which contains @@ -106,6 +107,7 @@ class Message(object): if not 'vol' in msg.params: # prevent clipping on some Lyrebird tracks msg.params['vol'] = .8 + msg.lightChange = data['light'] if 'light' in data else None msg.params['vol'] = float(msg.params['vol']) @@ -1577,6 +1579,9 @@ class Story(object): 'params': params, 'duration': duration }) + + if message.lightChange is not None: + self.hugvey.setLightStatus(message.lightChange) # 2019-02-22 temporary disable listening while playing audio: # if self.hugvey.google is not None: @@ -1663,17 +1668,18 @@ class Story(object): self.hugvey.google.stop() def calculateFinishesForMsg(self, msgId, depth = 0, checked = []): - # if msgId in checked: - # return [] - # - # checked.append(msgId) + if msgId in checked: + return [] + + checked.append(msgId) if not msgId in self.directionsPerMsg or len(self.directionsPerMsg[msgId]) < 1: # is finish return [msgId] - if depth > 100: - return [] + if depth == 500: + self.logger.warn(f"Very deep hidden message to calculate finish for: msgId {msgId}") +# return [] finishes = [] for d in self.directionsPerMsg[msgId]: @@ -1743,7 +1749,7 @@ class Story(object): def storeState(self): # TODO: stop stopwatch - fn = self.getStateFilename(self.hugvey.id) + fn = self.getStateFilename(self.hugvey.lightId) tmpfn = fn + '.tmp' self.stateSave = time.time() with open(tmpfn, 'wb') as fp: @@ -1756,7 +1762,7 @@ class Story(object): self.logger.debug(f"saved state to {fn}") def hasSavedState(self): - return self.hugveyHasSavedState(self.hugvey.id) + return self.hugveyHasSavedState(self.hugvey.lightId) @classmethod def hugveyHasSavedState(cls, hv_id): @@ -1765,7 +1771,7 @@ class Story(object): @classmethod def loadStoryFromState(cls, hugvey_state): # restart stopwatch - with open(cls.getStateFilename(hugvey_state.id), 'rb') as fp: + with open(cls.getStateFilename(hugvey_state.lightId), 'rb') as fp: story = pickle.load(fp) story.hugvey = hugvey_state diff --git a/www/js/hugvey_console.js b/www/js/hugvey_console.js index 14801fd..2515536 100644 --- a/www/js/hugvey_console.js +++ b/www/js/hugvey_console.js @@ -992,6 +992,17 @@ class Graph { "uploaded" ) : 'Auto-generated') ); + + let lightOptionNone = {'value': null} + let lightOptionOn = {'value': 1} + let lightOptionOff = {'value': 0} + + if(msg.hasOwnProperty('light')) { + if(msg['light'] === 1) lightOptionOn['selected'] = 'selected'; + if(msg['light'] === 0) lightOptionOff['selected'] = 'selected'; + if(msg['light'] === null) lightOptionNone['selected'] = 'selected'; + } + let msgInfoEl = crel( 'div', { 'class': 'msg__info' }, crel('div', { 'class':'btn btn--delete btn--delete-msg', @@ -1125,6 +1136,24 @@ class Graph { 'change': this.getEditEventListener() } } ) + ), + crel( 'label', + crel( 'span', { + "title": "What to do with the light when this message is triggered?" + }, 'Light change' ), + crel( 'select', { + 'name': msg['@id'] + '-light', + 'on': { + 'change': function(e) { + msg['light'] = e.target.value === "null" ? null : parseInt(e.target.value); + panopticon.graph.build(); + } + } + }, + crel('option', lightOptionNone, "Do nothing"), + crel('option', lightOptionOn, "Turn on"), + crel('option', lightOptionOff, "Turn off") + ) ) ); msgEl.appendChild( msgInfoEl ); @@ -1550,6 +1579,7 @@ class Graph { "text": "New", "start": false, "afterrunTime": 0.5, + "light": null, } this.data.push( msg ); @@ -1717,7 +1747,7 @@ class Graph { ...this.directions, ...this.diversions] let d = []; // let toRemove = ['sourceX', 'sourceY', 'targetX', 'targetY', 'x', 'y', 'vx', 'vy'] - let toRemove = ['sourceX', 'sourceY', 'targetX', 'targetY', 'vx', 'vy'] + let toRemove = ['sourceX', 'sourceY', 'targetX', 'targetY', 'x', 'y', 'vx', 'vy'] for ( let node of this.data ) { let n = {}; // console.log( node['source'] );