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

This commit is contained in:
Ruben van de Ven 2019-06-08 16:10:46 +02:00
parent 126c10b5ce
commit 39dbf0502a
3 changed files with 59 additions and 21 deletions

View File

@ -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()

View File

@ -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

View File

@ -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'] );