From cd66a7c6afce6537bccc47f67b32974cb6ccf1a1 Mon Sep 17 00:00:00 2001 From: Ruben van de Ven Date: Thu, 25 Apr 2019 11:12:27 +0200 Subject: [PATCH] First messages to light, and changes to Timeout (only when no other timeout) and ReplYContains (allow skip for color) diversions --- hugvey/central_command.py | 27 ++++++++++++++++++++++----- hugvey/story.py | 26 +++++++++++++++++++++++--- www/js/hugvey_console.js | 33 ++++++++++++++++++++++++--------- 3 files changed, 69 insertions(+), 17 deletions(-) diff --git a/hugvey/central_command.py b/hugvey/central_command.py index c6985b3..05f28b6 100644 --- a/hugvey/central_command.py +++ b/hugvey/central_command.py @@ -23,6 +23,7 @@ import threading from hugvey.voice import VoiceStorage import multiprocessing from hugvey.speech.recorder import Recorder +from pythonosc import udp_client mainLogger = logging.getLogger("hugvey") @@ -90,6 +91,13 @@ class CentralCommand(object): self.panopticon = Panopticon(self, self.config, self.voiceStorage) + self.lightConn = udp_client.SimpleUDPClient( + self.config['light']['ip'], + self.config['light']['port']) + +# logger.info("Send light /general 1") +# self.lightConn.send_message("/general", [1]) + def loadLanguages(self): logger.debug('load language files') @@ -348,6 +356,11 @@ class HugveyState(object): self.notShuttingDown = True # TODO: allow shutdown of object self.startMsgId = None self.eventLogger = eventLogger.getChild(f"{self.id}") + + self.lightConn = udp_client.SimpleUDPClient( + command.config['light']['ip'], + command.config['light']['port']) + def getStatus(self): if self.story.isFinished(): @@ -410,7 +423,6 @@ class HugveyState(object): # Allow for both the Hugvey Command, or the Story handle the event. self.loop.call_soon_threadsafe(self._queueEvent, msg) - def _queueEvent(self, msg): self.logger.debug(f"Queue event in hugvey loop: {msg}") self.eventQueue.put_nowait(msg) @@ -433,7 +445,7 @@ class HugveyState(object): if event['event'] == 'restart': self.restart() if event['event'] == 'finish': - self.finish() + self.story.finish() if event['event'] == 'resume': self.resume() @@ -508,12 +520,16 @@ class HugveyState(object): def finish(self): """Finish playback""" - self.logger.info('Restart') + self.logger.info('Finish') self.pause() - if self.story: - self.story.finish() + self.isRunning.clear() self.status = self.STATE_FINISHED + self.setLightStatus(True) + def setLightStatus(self, on): + status = 1 if on else 0 + self.logger.info(f"Send /hugvey {status}") + self.lightConn.send_message("/hugvey", [self.id, status]) def gone(self): '''Status to 'gone' as in, shutdown/crashed/whatever @@ -541,6 +557,7 @@ class HugveyState(object): self.streamer.triggerStart() self.story.setStoryData(self.command.languages[self.language_code]) + self.setLightStatus(False) await self.story.run(startMsgId) # self.story = None diff --git a/hugvey/story.py b/hugvey/story.py index c6e06a0..c7a9c17 100644 --- a/hugvey/story.py +++ b/hugvey/story.py @@ -13,6 +13,7 @@ import faulthandler from zmq.asyncio import Context import zmq import wave +from pythonosc import udp_client mainLogger = logging.getLogger("hugvey") logger = mainLogger.getChild("narrative") @@ -53,6 +54,7 @@ class Message(object): self.variableValues = {} self.parseForVariables() self.uuid = None # Have a unique id each time the message is played back. + self.color = None def setStory(self, story): self.story = story @@ -63,6 +65,7 @@ class Message(object): msg = message(data['@id'], data['text']) msg.isStart = data['beginning'] if 'beginning' in data else False msg.afterrunTime = data['afterrun'] if 'afterrun' in data else 0. + msg.color = data['color'] if 'color' in data else None if 'audio' in data and data['audio'] is not None: msg.audioFile = data['audio']['file'] msg.setStory(story) @@ -244,11 +247,14 @@ class Condition(object): def __init__(self, id): self.id = id self.method = None + self.type = None self.vars = {} @classmethod def initFromJson(conditionClass, data, story): condition = conditionClass(data['@id']) + condition.type = data['type'] + # TODO: should Condition be subclassed? if data['type'] == "replyContains": condition.method = condition._hasMetReplyContains @@ -538,7 +544,13 @@ class Diversion(object): if r is None: return - logger.info(f"Diverge: reply contains {self.id}") + + if 'notForColor' in self.params and self.params['notForColor']: + if story.currentMessage.color.lower() == self.params['notForColor'].lower(): + story.logger.debug(f"Skip diversion {self.id} because of section color") + return + + story.logger.info(f"Diverge: reply contains {self.id}") story.stats['diversions']['reply_contains'] += 1 msg = story.get(self.params['msgId']) @@ -589,6 +601,13 @@ class Diversion(object): if not story.lastMsgFinishTime: # not during play back return + + # not applicable when timeout is set + directions = story.getCurrentDirections() + for direction in directions: + for condition in direction.conditions: + if condition.type == 'timeout': + return now = story.timer.getElapsed() if now - story.lastMsgFinishTime < float(self.params['minTimeAfterMessage']): @@ -1143,9 +1162,10 @@ class Story(object): self.logger.info(f"Finished story for {self.hugvey.id}") self.hugvey.eventLogger.info("story: finished") self.stop() - self.hugvey.pause() self.finish_time = time.time() self.timer.pause() #stop google etc: - self.hugvey.isRunning.clear() + self.hugvey.finish() + + diff --git a/www/js/hugvey_console.js b/www/js/hugvey_console.js index 99cf050..7e24df5 100644 --- a/www/js/hugvey_console.js +++ b/www/js/hugvey_console.js @@ -444,6 +444,7 @@ class Graph { div['params']['regex'] = ""; div['params']['returnAfterStrand'] = true; div['params']['msgId'] = ""; + div['params']['notForColor'] = ""; } else if(type == 'timeout') { div['params']['interval'] = 20; @@ -592,15 +593,29 @@ class Graph { } }, 'Delete diversion'), crel('label', 'Regex', - crel('input', { - 'type': 'text', - 'value': div['params']['regex'], - 'placeholder': 'regex', - 'on': { - 'change': (e) => div['params']['regex'] = e.target.value - } - }) - ), + crel('input', { + 'type': 'text', + 'value': div['params']['regex'], + 'placeholder': 'regex', + 'on': { + 'change': (e) => div['params']['regex'] = e.target.value + } + }) + ), + crel('label', 'Ignore for color', + crel('input', { + 'type': 'text', // use text instead of color, as color doesn't allow for empty values + 'value': typeof div['params']['notForColor'] !== 'undefined' ? div['params']['notForColor'] : "", + 'on': { + 'change': function(e) { + if(e.target.value.length > 0 && e.target.value.substr(0,1) !== '#') { + alert("Don't forget to have a valid hex including the #-character, eg: #00ff00"); + } + div['params']['notForColor'] = e.target.value; + } + } + }) + ), crel('label', 'Return to point of departure afterwards', crel('input', returnAttrs) ),