Logging made fit for cutelog / client audio stream now on port = port_nr + hugvey_id'

This commit is contained in:
Ruben van de Ven 2019-03-23 18:18:52 +01:00
parent 3eb4c78ae4
commit d95709b9a1
10 changed files with 102 additions and 85 deletions

View file

@ -22,8 +22,8 @@ import queue
import threading import threading
from hugvey.voice import VoiceStorage from hugvey.voice import VoiceStorage
mainLogger = logging.getLogger("hugvey")
logger = logging.getLogger("command") logger = mainLogger.getChild("command")
# def exceptionEmitter(a): # def exceptionEmitter(a):
# print(a) # print(a)
@ -159,7 +159,7 @@ class CentralCommand(object):
while self.isRunning.is_set(): while self.isRunning.is_set():
hv_id, cmd = await self.commandQueue.get() hv_id, cmd = await self.commandQueue.get()
logger.info('Got command to send: {} {}'.format(hv_id, cmd)) logger.debug('Got command to send: {} {}'.format(hv_id, cmd))
zmqSend(s, hv_id, cmd) zmqSend(s, hv_id, cmd)
logger.warn('Stopping command sender') logger.warn('Stopping command sender')
@ -191,7 +191,7 @@ class CentralCommand(object):
async def eventListener(self): async def eventListener(self):
s = self.ctx.socket(zmq.SUB) s = self.ctx.socket(zmq.SUB)
s.bind(self.config['events']['listen_address']) s.bind(self.config['events']['listen_address'])
logger.info("Listen for events on: {}".format( logger.debug("Listen for events on: {}".format(
self.config['events']['listen_address'])) self.config['events']['listen_address']))
for id in self.hugvey_ids: for id in self.hugvey_ids:
@ -262,10 +262,9 @@ class HugveyState(object):
STATE_RUNNING = "running" STATE_RUNNING = "running"
def __init__(self, id: int, command: CentralCommand): def __init__(self, id: int, command: CentralCommand):
self.id = id self.id = id
self.command = command self.command = command
self.logger = logging.getLogger(f"hugvey{self.id}") self.logger = mainLogger.getChild(f"{self.id}").getChild("command")
self.loop = asyncio.new_event_loop() self.loop = asyncio.new_event_loop()
self.isConfigured = False self.isConfigured = False
self.isRunning = asyncio.Event(loop=self.loop) self.isRunning = asyncio.Event(loop=self.loop)
@ -323,8 +322,8 @@ class HugveyState(object):
print(awaitable) print(awaitable)
await awaitable await awaitable
except Exception as e: except Exception as e:
logger.exception(e) self.logger.exception(e)
logger.critical(f"Hugvey restart required but not implemented yet") self.logger.critical(f"Hugvey restart required but not implemented yet")
# TODO: restart # TODO: restart
@ -348,7 +347,7 @@ class HugveyState(object):
self.eventQueue = asyncio.Queue() # start event queue here, to avoid loop issues self.eventQueue = asyncio.Queue() # start event queue here, to avoid loop issues
while self.command.isRunning.is_set(): while self.command.isRunning.is_set():
event = await self.eventQueue.get() event = await self.eventQueue.get()
self.logger.info("Received: {}".format(event)) self.logger.debug("Received: {}".format(event))
if event['event'] == 'connection' and not self.isRunning.is_set(): if event['event'] == 'connection' and not self.isRunning.is_set():
self.restart() self.restart()
@ -462,7 +461,7 @@ class HugveyState(object):
self.streamer = AudioStreamer( self.streamer = AudioStreamer(
self.command.config['voice']['chunk'], self.command.config['voice']['chunk'],
self.ip, self.ip,
int(self.command.config['voice']['port'])) int(self.command.config['voice']['port']) + self.id)
if self.command.config['voyeur']: if self.command.config['voyeur']:
self.logger.warn("Debug on: Connecting Audio player") self.logger.warn("Debug on: Connecting Audio player")
@ -470,7 +469,7 @@ class HugveyState(object):
self.command.config['voice']['src_rate'], self.command.config['voice']['out_rate']) self.command.config['voice']['src_rate'], self.command.config['voice']['out_rate'])
self.streamer.addConsumer(self.player) self.streamer.addConsumer(self.player)
self.logger.info("Start Speech") self.logger.debug("Start Speech")
self.google = GoogleVoiceClient( self.google = GoogleVoiceClient(
hugvey=self, hugvey=self,
src_rate=self.command.config['voice']['src_rate'], src_rate=self.command.config['voice']['src_rate'],
@ -485,13 +484,13 @@ class HugveyState(object):
Start the audio streamer service Start the audio streamer service
''' '''
self.logger.info("Start audio stream") self.logger.debug("Start audio stream")
while self.notShuttingDown: while self.notShuttingDown:
await self.isRunning.wait() await self.isRunning.wait()
self.logger.info("Start audio stream") self.logger.debug("Start audio stream")
await self.getStreamer().run() await self.getStreamer().run()
self.logger.warn(f"stream has left the building from {self.ip}") self.logger.critical(f"stream has left the building from {self.ip}")
# if we end up here, the streamer finished, probably meaning hte hugvey shutdown # if we end up here, the streamer finished, probably meaning hte hugvey shutdown
self.gone() self.gone()

View file

@ -98,7 +98,7 @@ class VoiceServer(object):
while not self.stopped: while not self.stopped:
try: try:
address = "tcp://*:{}".format(self.voice_port) address = "tcp://*:{}".format(self.voice_port + self.hugvey.id)
self.voice_socket = self.ctx.socket(zmq.PUB) self.voice_socket = self.ctx.socket(zmq.PUB)
self.voice_socket.bind(address) self.voice_socket.bind(address)

View file

@ -1,7 +1,8 @@
import json import json
import logging import logging
logger = logging.getLogger("communication")
mainLogger = logging.getLogger("hugvey")
# hyper verbose log level. Have it here, becase it needs to be _somewhere_ # hyper verbose log level. Have it here, becase it needs to be _somewhere_
LOG_BS = 5 LOG_BS = 5
@ -11,14 +12,17 @@ def getTopic(hugvey_id):
def zmqSend(socket, hugvey_id, msg): def zmqSend(socket, hugvey_id, msg):
logger.info("SEND: {}".format(msg)) log = mainLogger.getChild(f"{hugvey_id}").getChild("communication")
log.debug("SEND: {}".format(msg))
msgData = json.dumps(msg) msgData = json.dumps(msg)
topic = getTopic(hugvey_id) topic = getTopic(hugvey_id)
logger.info("Send 0mq to {} containing {}".format(topic, msg)) log.debug("Send 0mq to {} containing {}".format(topic, msg))
socket.send_multipart([topic.encode(), msgData.encode()]) socket.send_multipart([topic.encode(), msgData.encode()])
async def zmqReceive(socket): async def zmqReceive(socket):
topic, msg = await socket.recv_multipart() topic, msg = await socket.recv_multipart()
hugvey_id = topic.decode()[2:] hugvey_id = topic.decode()[2:]
logger.info("Received 0mq messages for Hugvey #{} containing {}".format(hugvey_id, msg.decode())) mainLogger.getChild(f"{hugvey_id}").getChild("communication").debug(
"Received 0mq messages for Hugvey #{} containing {}".format(hugvey_id, msg.decode())
)
return int(hugvey_id), json.loads(msg.decode()) return int(hugvey_id), json.loads(msg.decode())

View file

@ -18,7 +18,8 @@ from urllib.parse import urlparse
from hugvey import central_command from hugvey import central_command
from hugvey.voice import VoiceStorage from hugvey.voice import VoiceStorage
logger = logging.getLogger("panopticon") mainLogger = logging.getLogger("hugvey")
logger = mainLogger.getChild("panopticon")
web_dir = os.path.join(os.path.split(__file__)[0], '..', 'www') web_dir = os.path.join(os.path.split(__file__)[0], '..', 'www')

View file

@ -18,14 +18,15 @@ import queue
import uuid import uuid
from hugvey.communication import LOG_BS from hugvey.communication import LOG_BS
mainLogger = logging.getLogger("hugvey")
logger = logging.getLogger("speech") logger = mainLogger.getChild("speech")
class RequireRestart(Exception): class RequireRestart(Exception):
pass pass
class GoogleVoiceClient(object): class GoogleVoiceClient(object):
def __init__(self, hugvey, src_rate, credential_file, language_code = "en_GB"): def __init__(self, hugvey, src_rate, credential_file, language_code = "en_GB"):
self.logger = mainLogger.getChild(f"{hugvey.id}").getChild('speech')
self.src_rate = src_rate self.src_rate = src_rate
self.hugvey = hugvey self.hugvey = hugvey
self.language_code = language_code self.language_code = language_code
@ -60,7 +61,7 @@ class GoogleVoiceClient(object):
if self.language_code == language_code: if self.language_code == language_code:
return return
logger.info("Change language from {} to {}".format(self.language_code, language_code)) self.logger.info("Change language from {} to {}".format(self.language_code, language_code))
self.language_code = language_code self.language_code = language_code
self.restart = True self.restart = True
@ -71,7 +72,7 @@ class GoogleVoiceClient(object):
while not self.toBeShutdown: while not self.toBeShutdown:
try: try:
self.isRunning.wait() self.isRunning.wait()
logger.info("Starting Google Voice") self.logger.info("Starting Google Voice")
self.speech_client = speech.SpeechClient() self.speech_client = speech.SpeechClient()
config = types.RecognitionConfig( config = types.RecognitionConfig(
@ -88,7 +89,7 @@ class GoogleVoiceClient(object):
responses = self.speech_client.streaming_recognize( responses = self.speech_client.streaming_recognize(
self.streaming_config, requests) self.streaming_config, requests)
logger.info("Starting voice loop") self.logger.info("Starting voice loop")
for response in responses: for response in responses:
if not response.results: if not response.results:
continue continue
@ -117,12 +118,12 @@ class GoogleVoiceClient(object):
# Display the transcription of the top alternative. # Display the transcription of the top alternative.
transcript = result.alternatives[0].transcript transcript = result.alternatives[0].transcript
# logger.debug("Text: ".format(transcript)) # self.logger.debug("Text: ".format(transcript))
if not result.is_final: if not result.is_final:
logger.debug(f"Text: {transcript}") self.logger.debug(f"Text: {transcript}")
else: else:
logger.info(f"Text: {transcript}") self.logger.info(f"Text: {transcript}")
msg = { msg = {
"event": "speech", "event": "speech",
@ -137,12 +138,12 @@ class GoogleVoiceClient(object):
raise RequireRestart("Restart required") raise RequireRestart("Restart required")
if self.toBeShutdown: if self.toBeShutdown:
logger.warn("Stopping voice loop") self.logger.warn("Stopping voice loop")
break break
except RequireRestart as e: except RequireRestart as e:
logger.warn("Restart Google Voice. Language: {}".format(self.language_code)) self.logger.warn("Restart Google Voice. Language: {}".format(self.language_code))
except Exception as e: except Exception as e:
logger.critical(f"Crashed Google Voice: {e}") self.logger.critical(f"Crashed Google Voice: {e}")
def receive(self, chunk): def receive(self, chunk):

View file

@ -2,8 +2,8 @@ import pyaudio
import logging import logging
import audioop import audioop
mainLogger = logging.getLogger("hugvey")
logger = logging.getLogger("player") logger = mainLogger.getChild("player")
class Player: class Player:
""" """

View file

@ -6,7 +6,8 @@ import logging
from zmq.asyncio import Context from zmq.asyncio import Context
import zmq import zmq
logger = logging.getLogger("streamer") mainLogger = logging.getLogger("hugvey")
logger = mainLogger.getChild("streamer")
class AudioStreamer(object): class AudioStreamer(object):
def __init__(self, chunk, address: str, port: int): def __init__(self, chunk, address: str, port: int):
@ -37,7 +38,7 @@ class AudioStreamer(object):
# s.connect((self.address, self.port)) # s.connect((self.address, self.port))
# #
try: try:
while self.isRunning: while self.isRunning:
data = await self.socket.recv() data = await self.socket.recv()
# logger.debug('chunk received') # logger.debug('chunk received')
self.process(data) self.process(data)

View file

@ -7,7 +7,8 @@ import urllib.parse
from .communication import LOG_BS from .communication import LOG_BS
from tornado.httpclient import AsyncHTTPClient, HTTPRequest from tornado.httpclient import AsyncHTTPClient, HTTPRequest
logger = logging.getLogger("narrative") mainLogger = logging.getLogger("hugvey")
logger = mainLogger.getChild("narrative")
class Utterance(object): class Utterance(object):
"""Part of a reply""" """Part of a reply"""
@ -44,6 +45,7 @@ class Message(object):
def setStory(self, story): def setStory(self, story):
self.story = story self.story = story
self.logger = story.logger.getChild("message")
@classmethod @classmethod
def initFromJson(message, data, story): def initFromJson(message, data, story):
@ -70,7 +72,7 @@ class Message(object):
def setVariable(self, name, value): def setVariable(self, name, value):
if name not in self.variables: if name not in self.variables:
logger.critical("Set nonexisting variable") self.logger.critical("Set nonexisting variable")
return return
if self.variableValues[name] == value: if self.variableValues[name] == value:
@ -78,21 +80,21 @@ class Message(object):
self.variableValues[name] = value self.variableValues[name] = value
logger.warn(f"Set variable, now fetch {name}") self.story.warn(f"Set variable, now fetch {name}")
if not None in self.variableValues.values(): if not None in self.variableValues.values():
logger.warn(f"now fetch indeed {name}") self.story.warn(f"now fetch indeed {name}")
asyncio.get_event_loop().create_task(self.getAudioFilePath()) asyncio.get_event_loop().create_task(self.getAudioFilePath())
# asyncio.get_event_loop().call_soon_threadsafe(self.getAudioFilePath) # asyncio.get_event_loop().call_soon_threadsafe(self.getAudioFilePath)
logger.warn(f"started {name}") self.story.warn(f"started {name}")
def getText(self): def getText(self):
# sort reverse to avoid replacing the wrong variable # sort reverse to avoid replacing the wrong variable
self.variables.sort(key=len, reverse=True) self.variables.sort(key=len, reverse=True)
text = self.text text = self.text
logger.info(f"Getting text for {self.id}") self.logger.debug(f"Getting text for {self.id}")
logger.debug(self.variables) self.logger.debug(self.variables)
for var in self.variables: for var in self.variables:
logger.debug(f"try replacing ${var} with {self.variableValues[var]} in {text}") self.logger.debug(f"try replacing ${var} with {self.variableValues[var]} in {text}")
replacement = self.variableValues[var] if (self.variableValues[var] is not None) else "nothing" #TODO: translate nothing to each language replacement = self.variableValues[var] if (self.variableValues[var] is not None) else "nothing" #TODO: translate nothing to each language
text = text.replace('$'+var, replacement) text = text.replace('$'+var, replacement)
return text return text
@ -134,7 +136,7 @@ class Message(object):
if self.audioFile is not None: if self.audioFile is not None:
return self.audioFile return self.audioFile
logger.warn(f"Fetching audio for {self.getText()}") self.logger.debug(f"Fetching audio for {self.getText()}")
async with self.filenameFetchLock: async with self.filenameFetchLock:
client = AsyncHTTPClient() client = AsyncHTTPClient()
queryString = urllib.parse.urlencode({ queryString = urllib.parse.urlencode({
@ -146,14 +148,14 @@ class Message(object):
url = f"http://localhost:{self.story.panopticon_port}/voice?{queryString}", url = f"http://localhost:{self.story.panopticon_port}/voice?{queryString}",
method="GET" method="GET"
) )
logger.log(LOG_BS, request.url) self.logger.log(LOG_BS, request.url)
response = await client.fetch(request) response = await client.fetch(request)
if response.code != 200: if response.code != 200:
logger.critical(f"Error when fetching filename: {response.code} for {queryString}") self.logger.critical(f"Error when fetching filename: {response.code} for {queryString}")
return None return None
logger.warn(f"Fetched audio for {self.getText()}") self.logger.debug(f"Fetched audio for {self.getText()}")
return response.body.decode().strip() return response.body.decode().strip()
@ -242,11 +244,11 @@ class Condition(object):
if 'onlyIfNoReply' in self.vars and self.vars['onlyIfNoReply']: if 'onlyIfNoReply' in self.vars and self.vars['onlyIfNoReply']:
if story.currentReply and story.currentReply is not None and story.currentReply.hasUtterances(): if story.currentReply and story.currentReply is not None and story.currentReply.hasUtterances():
logger.log(LOG_BS, f'Only if no reply has text! {story.currentReply.getText()}') story.logger.log(LOG_BS, f'Only if no reply has text! {story.currentReply.getText()}')
# 'onlyIfNoReply': only use this timeout if participants doesn't speak. # 'onlyIfNoReply': only use this timeout if participants doesn't speak.
return False return False
# else: # else:
# logger.debug('Only if no reply has no text yet!') # story.logger.debug('Only if no reply has no text yet!')
hasMetTimeout = now - story.lastMsgFinishTime >= float(self.vars['seconds']) hasMetTimeout = now - story.lastMsgFinishTime >= float(self.vars['seconds'])
if not hasMetTimeout: if not hasMetTimeout:
@ -278,12 +280,12 @@ class Condition(object):
self.vars['regexCompiled'] = re.compile(self.vars['regex']) self.vars['regexCompiled'] = re.compile(self.vars['regex'])
t = r.getText().lower() t = r.getText().lower()
logger.log(LOG_BS, 'attempt regex: {} on {}'.format(self.vars['regex'], t)) story.logger.log(LOG_BS, 'attempt regex: {} on {}'.format(self.vars['regex'], t))
result = self.vars['regexCompiled'].search(t) result = self.vars['regexCompiled'].search(t)
if result is None: if result is None:
#if there is something to match, but not found, it's never ok #if there is something to match, but not found, it's never ok
return False return False
logger.debug('Got match on {}'.format(self.vars['regex'])) story.logger.debug('Got match on {}'.format(self.vars['regex']))
if ('instantMatch' in self.vars and self.vars['instantMatch']) or not r.isSpeaking(): if ('instantMatch' in self.vars and self.vars['instantMatch']) or not r.isSpeaking():
# try to avoid setting variables for intermediate strings # try to avoid setting variables for intermediate strings
@ -292,19 +294,19 @@ class Condition(object):
story.setVariableValue(captureGroup, results[captureGroup]) story.setVariableValue(captureGroup, results[captureGroup])
if 'instantMatch' in self.vars and self.vars['instantMatch']: if 'instantMatch' in self.vars and self.vars['instantMatch']:
logger.info(f"Instant match on {self.vars['regex']}, {self.vars}") story.logger.info(f"Instant match on {self.vars['regex']}, {self.vars}")
return True return True
# TODO: implement 'instant match' -> don't wait for isFinished() # TODO: implement 'instant match' -> don't wait for isFinished()
if r.isSpeaking(): if r.isSpeaking():
logger.log(LOG_BS, f"is speaking: {r.getLastUtterance().text} - {r.getLastUtterance().startTime}") story.logger.log(LOG_BS, f"is speaking: {r.getLastUtterance().text} - {r.getLastUtterance().startTime}")
return False return False
# print(self.vars) # print(self.vars)
# either there's a match, or nothing to match at all # either there's a match, or nothing to match at all
if 'delays' in self.vars: if 'delays' in self.vars:
if story.lastMsgFinishTime is None: if story.lastMsgFinishTime is None:
logger.debug("not finished playback yet") story.logger.debug("not finished playback yet")
return False return False
# time between finishing playback and ending of speaking: # time between finishing playback and ending of speaking:
replyDuration = r.getLastUtterance().endTime - story.lastMsgFinishTime replyDuration = r.getLastUtterance().endTime - story.lastMsgFinishTime
@ -312,12 +314,12 @@ class Condition(object):
for delay in delays: for delay in delays:
if replyDuration > float(delay['minReplyDuration']): if replyDuration > float(delay['minReplyDuration']):
timeSinceReply = story.timer.getElapsed() - r.getLastUtterance().endTime timeSinceReply = story.timer.getElapsed() - r.getLastUtterance().endTime
logger.log(LOG_BS, f"check delay duration is now {replyDuration}, already waiting for {timeSinceReply}, have to wait {delay['waitTime']}") story.logger.log(LOG_BS, f"check delay duration is now {replyDuration}, already waiting for {timeSinceReply}, have to wait {delay['waitTime']}")
if timeSinceReply > float(delay['waitTime']): if timeSinceReply > float(delay['waitTime']):
return True return True
break # don't check other delays break # don't check other delays
# wait for delay to match # wait for delay to match
logger.debug("Wait for it...") story.logger.debug("Wait for it...")
return False return False
# There is a match and no delay say, person finished speaking. Go ahead sir! # There is a match and no delay say, person finished speaking. Go ahead sir!
@ -425,10 +427,10 @@ class Diversion(object):
story.stats['diversions']['no_response'] += 1 story.stats['diversions']['no_response'] += 1
msg = story.get(self.params['msgId']) msg = story.get(self.params['msgId'])
if msg is None: if msg is None:
logger.critical(f"Not a valid message id for diversion: {self.params['msgId']}") story.logger.critical(f"Not a valid message id for diversion: {self.params['msgId']}")
return return
logger.info(f"Diverge: No response {self.id} {story.stats}") story.logger.info(f"Diverge: No response {self.id} {story.stats}")
self.returnMessage = msgTo self.returnMessage = msgTo
await story.setCurrentMessage(msg) await story.setCurrentMessage(msg)
story.currentDiversion = self story.currentDiversion = self
@ -437,7 +439,7 @@ class Diversion(object):
return return
async def _returnAfterNoResponse(self, story): async def _returnAfterNoResponse(self, story):
logger.info(f"Finalise diversion: {self.id}") story.logger.info(f"Finalise diversion: {self.id}")
story.stats['consecutiveSilentTimeouts'] = 0 # reset counter after diverging story.stats['consecutiveSilentTimeouts'] = 0 # reset counter after diverging
if self.params['returnAfterStrand']: if self.params['returnAfterStrand']:
await story.setCurrentMessage(self.returnMessage) await story.setCurrentMessage(self.returnMessage)
@ -525,6 +527,7 @@ class Story(object):
self.events = [] # queue of received events self.events = [] # queue of received events
self.commands = [] # queue of commands to send self.commands = [] # queue of commands to send
self.log = [] # all nodes/elements that are triggered self.log = [] # all nodes/elements that are triggered
self.logger = mainLogger.getChild(f"{self.hugvey.id}").getChild("story")
self.currentMessage = None self.currentMessage = None
self.currentDiversion = None self.currentDiversion = None
self.currentReply = None self.currentReply = None
@ -534,11 +537,11 @@ class Story(object):
self.variables = {} self.variables = {}
def pause(self): def pause(self):
logger.debug('pause hugvey') self.logger.debug('pause hugvey')
self.timer.pause() self.timer.pause()
def resume(self): def resume(self):
logger.debug('resume hugvey') self.logger.debug('resume hugvey')
self.timer.resume() self.timer.resume()
def getLogSummary(self): def getLogSummary(self):
@ -559,7 +562,7 @@ class Story(object):
def setVariableValue(self, name, value): def setVariableValue(self, name, value):
if name not in self.variables: if name not in self.variables:
logger.warn(f"Set variable that is not needed in the story: {name}") self.logger.warn(f"Set variable that is not needed in the story: {name}")
self.variableValues[name] = value self.variableValues[name] = value
for message in self.variables[name]: for message in self.variables[name]:
@ -586,18 +589,18 @@ class Story(object):
obj = className.initFromJson(el, self) obj = className.initFromJson(el, self)
self.add(obj) self.add(obj)
logger.debug(self.elements) self.logger.debug(self.elements)
logger.debug(self.directionsPerMsg) self.logger.debug(self.directionsPerMsg)
self.diversions = [el for el in self.elements.values() if type(el) == Diversion] self.diversions = [el for el in self.elements.values() if type(el) == Diversion]
if currentId: if currentId:
self.currentMessage = self.get(currentId) self.currentMessage = self.get(currentId)
if self.currentMessage: if self.currentMessage:
logger.info( self.logger.info(
f"Reinstantiated current message: {self.currentMessage.id}") f"Reinstantiated current message: {self.currentMessage.id}")
else: else:
logger.warn( self.logger.warn(
"Could not reinstatiate current message. Starting over") "Could not reinstatiate current message. Starting over")
# Register variables # Register variables
@ -610,7 +613,7 @@ class Story(object):
self.registerVariable(var, msg) self.registerVariable(var, msg)
logger.info(f'has variables: {self.variables}') self.logger.info(f'has variables: {self.variables}')
def reset(self): def reset(self):
self.timer.reset() self.timer.reset()
@ -672,7 +675,7 @@ class Story(object):
return [el for el in self.elements.values() if type(el) == Message] return [el for el in self.elements.values() if type(el) == Message]
def stop(self): def stop(self):
logger.info("Stop Story") self.logger.info("Stop Story")
if self.isRunning: if self.isRunning:
self.isRunning = False self.isRunning = False
@ -681,7 +684,7 @@ class Story(object):
nr = len(self.events) nr = len(self.events)
for i in range(nr): for i in range(nr):
e = self.events.pop(0) e = self.events.pop(0)
logger.info("handle '{}'".format(e)) self.logger.debug("handle '{}'".format(e))
if e['event'] == "exit": if e['event'] == "exit":
self.stop() self.stop()
if e['event'] == 'connect': if e['event'] == 'connect':
@ -697,16 +700,16 @@ class Story(object):
# 2019-02-22 temporary disable listening while playing audio: # 2019-02-22 temporary disable listening while playing audio:
# if self.hugvey.google is not None: # if self.hugvey.google is not None:
# logger.warn("Temporary 'fix' -> resume recording?") # self.logger.warn("Temporary 'fix' -> resume recording?")
# self.hugvey.google.resume() # self.hugvey.google.resume()
if self.currentMessage.id not in self.directionsPerMsg: if self.currentMessage.id not in self.directionsPerMsg:
if self.currentDiversion is not None: if self.currentDiversion is not None:
logger.info("end of diversion") self.logger.info("end of diversion")
await self.currentDiversion.finalise(self) await self.currentDiversion.finalise(self)
self.currentDiversion = None self.currentDiversion = None
else: else:
logger.info("THE END!") self.logger.info("THE END!")
self.stop() self.stop()
return return
@ -719,7 +722,7 @@ class Story(object):
timeDiff = self.timer.getElapsed() - self.previousReply.forMessage.getFinishedTime() timeDiff = self.timer.getElapsed() - self.previousReply.forMessage.getFinishedTime()
if self.previousReply.forMessage.afterrunTime > timeDiff: if self.previousReply.forMessage.afterrunTime > timeDiff:
#interrupt only in given interval: #interrupt only in given interval:
logger.warn("Interrupt message, replay {}".format(self.previousReply.forMessage.id)) self.logger.warn("Interrupt message, replay {}".format(self.previousReply.forMessage.id))
self.currentReply = self.previousReply self.currentReply = self.previousReply
self.previousReply.forMessage.interruptCount += 1 self.previousReply.forMessage.interruptCount += 1
self.currentMessage = await self.setCurrentMessage(self.previousReply.forMessage, self.previousReply) self.currentMessage = await self.setCurrentMessage(self.previousReply.forMessage, self.previousReply)
@ -727,6 +730,7 @@ class Story(object):
# log if somebody starts speaking # log if somebody starts speaking
# TODO: implement interrupt # TODO: implement interrupt
if self.currentReply is None: if self.currentReply is None:
self.logger.info("Start speaking")
self.currentReply= Reply(self.currentMessage) self.currentReply= Reply(self.currentMessage)
utterance = self.currentReply.getActiveUtterance(self.timer.getElapsed()) utterance = self.currentReply.getActiveUtterance(self.timer.getElapsed())
@ -741,7 +745,7 @@ class Story(object):
for direction in directions: for direction in directions:
for condition in direction.conditions: for condition in direction.conditions:
if condition.isMet(self): if condition.isMet(self):
logger.info("Condition is met: {0}, going to {1}".format( self.logger.info("Condition is met: {0}, going to {1}".format(
condition.id, direction.msgTo.id)) condition.id, direction.msgTo.id))
direction.setMetCondition(condition) direction.setMetCondition(condition)
self.addToLog(condition) self.addToLog(condition)
@ -772,7 +776,7 @@ class Story(object):
""" """
loopDuration = 0.1 # Configure fps loopDuration = 0.1 # Configure fps
lastTime = time.time() lastTime = time.time()
logger.info("Start renderer") self.logger.debug("Start renderer")
while self.isRunning: while self.isRunning:
if self.isRunning is False: if self.isRunning is False:
break break
@ -797,14 +801,14 @@ class Story(object):
await asyncio.sleep(max(0, loopDuration - (t - lastTime))) await asyncio.sleep(max(0, loopDuration - (t - lastTime)))
lastTime = t lastTime = t
logger.info("Stop renderer") self.logger.debug("Stop renderer")
async def setCurrentMessage(self, message, useReply = None): async def setCurrentMessage(self, message, useReply = None):
""" """
Use Reply allows to pre-initiate a reply to use with the message. This is used eg. when doing an interruption. Use Reply allows to pre-initiate a reply to use with the message. This is used eg. when doing an interruption.
""" """
if self.currentMessage and not self.lastMsgFinishTime: if self.currentMessage and not self.lastMsgFinishTime:
logger.info("Interrupt playback {}".format(self.currentMessage.id)) self.logger.info("Interrupt playback {}".format(self.currentMessage.id))
# message is playing # message is playing
self.hugvey.sendCommand({ self.hugvey.sendCommand({
'action': 'stop', 'action': 'stop',
@ -823,7 +827,7 @@ class Story(object):
# self.previousReply = self.currentReply # we can use this for interrptions # self.previousReply = self.currentReply # we can use this for interrptions
# self.currentReply = self.currentMessage.reply # self.currentReply = self.currentMessage.reply
logger.info("Current message: ({0}) \"{1}\"".format( self.logger.info("Current message: ({0}) \"{1}\"".format(
message.id, message.text)) message.id, message.text))
self.addToLog(message) self.addToLog(message)
# TODO: prep events & timer etc. # TODO: prep events & timer etc.
@ -837,14 +841,14 @@ class Story(object):
# 2019-02-22 temporary disable listening while playing audio: # 2019-02-22 temporary disable listening while playing audio:
# if self.hugvey.google is not None: # if self.hugvey.google is not None:
# logger.warn("Temporary 'fix' -> stop recording") # self.logger.warn("Temporary 'fix' -> stop recording")
# self.hugvey.google.pause() # self.hugvey.google.pause()
logger.debug("Pending directions: ") self.logger.debug("Pending directions: ")
for direction in self.getCurrentDirections(): for direction in self.getCurrentDirections():
conditions = [c.id for c in direction.conditions] conditions = [c.id for c in direction.conditions]
logger.debug( self.logger.debug(
"- {0} -> {1} (when: {2}) ".format(direction.msgFrom.id, direction.msgTo.id, conditions)) "- {0} -> {1} (when: {2}) ".format(direction.msgFrom.id, direction.msgTo.id, conditions))
def getCurrentDirections(self): def getCurrentDirections(self):
@ -854,7 +858,7 @@ class Story(object):
return self.directionsPerMsg[self.currentMessage.id] return self.directionsPerMsg[self.currentMessage.id]
async def run(self, customStartMsgId = None): async def run(self, customStartMsgId = None):
logger.info("Starting story") self.logger.info("Starting story")
self.timer.reset() self.timer.reset()
self.isRunning = True self.isRunning = True
if customStartMsgId is not None: if customStartMsgId is not None:
@ -871,7 +875,7 @@ class Story(object):
return False return False
def finish(self): def finish(self):
logger.info(f"Finished story for {self.hugvey.id}") self.logger.info(f"Finished story for {self.hugvey.id}")
self.hugvey.pause() self.hugvey.pause()
self.finish_time = time.time() self.finish_time = time.time()
self.timer.pause() self.timer.pause()

View file

@ -8,7 +8,8 @@ from hashlib import sha1
import asyncio import asyncio
from tornado.httpclient import AsyncHTTPClient, HTTPRequest from tornado.httpclient import AsyncHTTPClient, HTTPRequest
logger = logging.getLogger("voice") mainLogger = logging.getLogger("hugvey")
logger = mainLogger.getChild("voice")
class VoiceStorage(object): class VoiceStorage(object):
""" """

View file

@ -37,7 +37,13 @@ if __name__ == '__main__':
# default: "%(asctime)s %(hostname)s %(name)s[%(process)d] %(levelname)s %(message)s" # default: "%(asctime)s %(hostname)s %(name)s[%(process)d] %(levelname)s %(message)s"
fmt="%(asctime)s %(hostname)s %(name)s[%(process)d,%(threadName)s] %(levelname)s %(message)s" fmt="%(asctime)s %(hostname)s %(name)s[%(process)d,%(threadName)s] %(levelname)s %(message)s"
) )
logger = logging.getLogger("hugvey")
# logger.setLevel(1) # to send all records to cutelog
socket_handler = logging.handlers.SocketHandler('127.0.0.1', 19996) # default listening address
logger.addHandler(socket_handler);
logger.info("Start server")
command = CentralCommand(args=args, debug_mode=args.verbose > 0) command = CentralCommand(args=args, debug_mode=args.verbose > 0)
command.loadConfig(args.config) command.loadConfig(args.config)
command.start() command.start()