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:
parent
126c10b5ce
commit
39dbf0502a
3 changed files with 59 additions and 21 deletions
|
@ -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,7 +606,8 @@ class HugveyState(object):
|
|||
if self.google:
|
||||
self.google.setLanguage(language_code)
|
||||
|
||||
def pause(self):
|
||||
def pause(self, log = True):
|
||||
if log:
|
||||
self.logger.info('Pause')
|
||||
if self.google:
|
||||
self.google.pause()
|
||||
|
@ -616,8 +616,9 @@ 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"""
|
||||
if log:
|
||||
self.logger.info('Resume')
|
||||
if self.google:
|
||||
self.google.resume()
|
||||
|
@ -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()
|
||||
|
||||
|
|
|
@ -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'])
|
||||
|
||||
|
@ -1578,6 +1580,9 @@ class Story(object):
|
|||
'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:
|
||||
# self.logger.warn("Temporary 'fix' -> stop recording")
|
||||
|
@ -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
|
||||
|
|
|
@ -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'] );
|
||||
|
|
Loading…
Reference in a new issue