Deepcopy story data and config changes

This commit is contained in:
Hugvey Central Command 2019-05-11 15:23:55 +02:00
parent 484542de8d
commit 43e3e52f2a
6 changed files with 100 additions and 102 deletions

View file

@ -93,7 +93,7 @@ chown=pi:pi
## Deploy / usefull commands ## Deploy / usefull commands
```bash ```bash
for i in {1..6}; do rsync -av ~/hugvey/ pi@hugvey$i.local:/home/pi/hugvey/ --exclude=www --exclude=venv --exclude=local --exclude=*.pyc --exclude=.git; done for i in {1..26}; do echo $i; rsync -av ~/hugvey/ pi@hugvey$i.local:/home/pi/hugvey/ --exclude=www --exclude=venv --exclude=local --exclude=*.pyc --exclude=.git --exclude=recordings --exclude=/voice* --exclude=/pd; done
``` ```
```bash ```bash
@ -204,4 +204,4 @@ times occured/only on n-th instance: determines the order of diversions of the s
## 4G Modem ## 4G Modem
Visit 192.168.5.1 Visit 192.168.5.1
The password is at the bottom of the device. The password is at the bottom of the device.

View file

@ -5,7 +5,7 @@ voice:
input_rate: 44100 input_rate: 44100
target_rate: 16000 target_rate: 16000
port: 4444 port: 4444
input_name: 'AK5371' input_name: 'USB Audio Device'
output_name: 'USB Audio Device' output_name: 'USB Audio Device'
input_mixer: 'Mic' input_mixer: 'Mic'
output_mixer: 'PCM' output_mixer: 'PCM'
@ -13,6 +13,3 @@ voice:
output_volume: 30 output_volume: 30
file_address: "http://hugveycmd.local:8888" file_address: "http://hugveycmd.local:8888"
output_driver: pulseaudio output_driver: pulseaudio

View file

@ -24,6 +24,7 @@ from hugvey.voice import VoiceStorage
import multiprocessing import multiprocessing
from hugvey.speech.recorder import Recorder from hugvey.speech.recorder import Recorder
from pythonosc import udp_client from pythonosc import udp_client
import copy
mainLogger = logging.getLogger("hugvey") mainLogger = logging.getLogger("hugvey")
@ -67,7 +68,7 @@ class CentralCommand(object):
self.languageFiles = {} self.languageFiles = {}
self.languageConfig = {} self.languageConfig = {}
self.args = args # cli args self.args = args # cli args
eventLogger.addHandler(logging.handlers.QueueHandler(self.logQueue)) eventLogger.addHandler(logging.handlers.QueueHandler(self.logQueue))
def loadConfig(self, filename): def loadConfig(self, filename):
@ -85,14 +86,14 @@ class CentralCommand(object):
self.hugvey_ids = [i + 1 for i in range(self.config['hugveys'])] self.hugvey_ids = [i + 1 for i in range(self.config['hugveys'])]
self.loadLanguages() self.loadLanguages()
voice_dir = os.path.join(self.config['web']['files_dir'], 'voices') voice_dir = os.path.join(self.config['web']['files_dir'], 'voices')
self.voiceStorage = VoiceStorage(voice_dir, self.languageConfig) self.voiceStorage = VoiceStorage(voice_dir, self.languageConfig)
self.panopticon = Panopticon(self, self.config, self.voiceStorage) self.panopticon = Panopticon(self, self.config, self.voiceStorage)
def loadLanguages(self): def loadLanguages(self):
logger.debug('load language files') logger.debug('load language files')
self.languages = {} self.languages = {}
@ -116,7 +117,7 @@ class CentralCommand(object):
# if not hv.story: # if not hv.story:
# status['status'] = 'off' # status['status'] = 'off'
# return status # return status
status['status'] = hv.getStatus() status['status'] = hv.getStatus()
status['language'] = hv.language_code status['language'] = hv.language_code
status['light_id'] = hv.lightId status['light_id'] = hv.lightId
@ -126,7 +127,7 @@ class CentralCommand(object):
# status['history'] = hv.story.getLogSummary() # disabled as it is a bit slow. We now have eventLog # status['history'] = hv.story.getLogSummary() # disabled as it is a bit slow. We now have eventLog
# status['counts'] = {t: len(a) for t, a in status['history'].items() if t != 'directions' } # 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['counts'] = {} if not hv.story else hv.story.getLogCounts()
status['duration'] = 0 if not hv.story else hv.story.timer.getElapsed() status['duration'] = 0 if not hv.story else hv.story.timer.getElapsed()
return status return status
@ -139,10 +140,10 @@ class CentralCommand(object):
'logbookId': None, 'logbookId': None,
'logbook': [], 'logbook': [],
} }
#use this to test if any threads stay open #use this to test if any threads stay open
# eg. after killing/dying of a hugvey # eg. after killing/dying of a hugvey
# print(threading.enumerate()) # print(threading.enumerate())
for hv_id in self.hugvey_ids: for hv_id in self.hugvey_ids:
status['hugveys'].append(self.getHugveyStatus(hv_id, selected_id == hv_id)) status['hugveys'].append(self.getHugveyStatus(hv_id, selected_id == hv_id))
@ -151,7 +152,7 @@ class CentralCommand(object):
if self.hugveys[selected_id].recorder: if self.hugveys[selected_id].recorder:
status['logbook'] = self.hugveys[selected_id].recorder.currentLog status['logbook'] = self.hugveys[selected_id].recorder.currentLog
status['logbookId'] = selected_id status['logbookId'] = selected_id
return status return status
def commandHugvey(self, hv_id, msg): def commandHugvey(self, hv_id, msg):
@ -169,8 +170,8 @@ class CentralCommand(object):
def _queueCommand(self, hv_id, msg): def _queueCommand(self, hv_id, msg):
self.commandQueue.put_nowait((hv_id, msg)) self.commandQueue.put_nowait((hv_id, msg))
def commandLight(self, route, data): def commandLight(self, route, data):
""" """
Buffer light commands Buffer light commands
@ -215,13 +216,13 @@ class CentralCommand(object):
logger.warn('Stopping command sender') logger.warn('Stopping command sender')
s.close() s.close()
async def lightSender(self): async def lightSender(self):
lightConn = udp_client.SimpleUDPClient( lightConn = udp_client.SimpleUDPClient(
self.config['light']['ip'], self.config['light']['ip'],
self.config['light']['port']) self.config['light']['port'])
logger.info(f"Ready to send light commands to: {self.config['light']['ip']}:{self.config['light']['port']}") logger.info(f"Ready to send light commands to: {self.config['light']['ip']}:{self.config['light']['port']}")
while self.isRunning.is_set(): while self.isRunning.is_set():
@ -232,7 +233,7 @@ class CentralCommand(object):
logger.warn('Stopping light sender') logger.warn('Stopping light sender')
lightConn._sock.close() lightConn._sock.close()
async def redLightController(self): async def redLightController(self):
""" """
Every second, check if no hugveys are available. If so, the red light should be Every second, check if no hugveys are available. If so, the red light should be
@ -264,7 +265,7 @@ class CentralCommand(object):
thread = threading.Thread( thread = threading.Thread(
target=self.hugveyStateRunner, args=(hugvey_id,), name=f"hugvey#{hugvey_id}") target=self.hugveyStateRunner, args=(hugvey_id,), name=f"hugvey#{hugvey_id}")
thread.start() thread.start()
def hugveyStateRunner(self, hugvey_id): def hugveyStateRunner(self, hugvey_id):
while self.isRunning.is_set(): while self.isRunning.is_set():
logger.info(f'Instantiate hugvey #{hugvey_id}') logger.info(f'Instantiate hugvey #{hugvey_id}')
@ -278,7 +279,7 @@ class CentralCommand(object):
return return
logger.critical(f'Hugvey stopped (crashed?). Reinstantiate after 5 sec') logger.critical(f'Hugvey stopped (crashed?). Reinstantiate after 5 sec')
time.sleep(5) time.sleep(5)
async def timerEmitter(self): async def timerEmitter(self):
""" """
This is fixed: a one hour loop with a collective moment 10-15 minutes, This is fixed: a one hour loop with a collective moment 10-15 minutes,
@ -288,25 +289,25 @@ class CentralCommand(object):
intervals = [ intervals = [
{ {
'start_time': 10*60, 'start_time': 10*60,
'duration': 5 * 60, 'duration': 5 * 60,
}, },
{ {
'start_time': 30*60, 'start_time': 30*60,
'duration': 5 * 60, 'duration': 5 * 60,
}, },
{ {
'start_time': 50*60, 'start_time': 50*60,
'duration': 5 * 60, 'duration': 5 * 60,
} }
] ]
self.start_time = time.time() self.start_time = time.time()
# TODO: emit start event # TODO: emit start event
while self.isRunning.is_set(): while self.isRunning.is_set():
pass pass
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'])
@ -319,7 +320,7 @@ class CentralCommand(object):
while self.isRunning.is_set(): while self.isRunning.is_set():
try: try:
hugvey_id, msg = await zmqReceive(s) hugvey_id, msg = await zmqReceive(s)
if hugvey_id not in self.hugvey_ids: if hugvey_id not in self.hugvey_ids:
logger.critical( logger.critical(
"Message from alien Hugvey: {}".format(hugvey_id)) "Message from alien Hugvey: {}".format(hugvey_id))
@ -355,7 +356,7 @@ class CentralCommand(object):
fn = await self.voiceStorage.requestFile(hv.language_code, text, isVariable) fn = await self.voiceStorage.requestFile(hv.language_code, text, isVariable)
if fn is None: if fn is None:
eventLogger.getChild(f"{hugvey_id}").critical("error: No voice file fetched, check logs.") eventLogger.getChild(f"{hugvey_id}").critical("error: No voice file fetched, check logs.")
fn = 'local/crash.wav' fn = 'local/crash.wav'
# TODO: trigger a repeat/crash event. # TODO: trigger a repeat/crash event.
await s.send_string(fn) await s.send_string(fn)
except Exception as e: except Exception as e:
@ -376,7 +377,7 @@ class CentralCommand(object):
self.catchException(self.lightSender())) self.catchException(self.lightSender()))
self.tasks['redLightController'] = self.loop.create_task( self.tasks['redLightController'] = self.loop.create_task(
self.catchException(self.redLightController())) self.catchException(self.redLightController()))
for hid in self.hugvey_ids: for hid in self.hugvey_ids:
self.tasks['voiceListener'] = self.loop.create_task( self.tasks['voiceListener'] = self.loop.create_task(
self.catchException(self.voiceListener(hid))) self.catchException(self.voiceListener(hid)))
@ -386,12 +387,12 @@ class CentralCommand(object):
self.panopticon_thread = threading.Thread( self.panopticon_thread = threading.Thread(
target=self.panopticon.start, name="Panopticon") target=self.panopticon.start, name="Panopticon")
self.panopticon_thread.start() self.panopticon_thread.start()
self.loop.run_forever() self.loop.run_forever()
def stop(self): def stop(self):
self.isRunning.clear() self.isRunning.clear()
async def catchException(self, awaitable): async def catchException(self, awaitable):
try: try:
# print(awaitable) # print(awaitable)
@ -405,7 +406,7 @@ class HugveyState(object):
"""Represents the state of a Hugvey client on the server. """Represents the state of a Hugvey client on the server.
Manages server connections & voice parsing etc. Manages server connections & voice parsing etc.
""" """
# all statusses can only go up or down, except for gone, which is an error state: # all statusses can only go up or down, except for gone, which is an error state:
# off <-> blocked <-> available <-> running <-> paused # off <-> blocked <-> available <-> running <-> paused
STATE_OFF = "off" STATE_OFF = "off"
@ -424,7 +425,7 @@ class HugveyState(object):
self.isConfigured = None self.isConfigured = None
self.isRunning = asyncio.Event(loop=self.loop) self.isRunning = asyncio.Event(loop=self.loop)
self.isRunning.clear() self.isRunning.clear()
self.eventQueue = None self.eventQueue = None
self.language_code = 'en-GB' self.language_code = 'en-GB'
self.story = None self.story = None
@ -435,24 +436,24 @@ class HugveyState(object):
self.notShuttingDown = True # TODO: allow shutdown of object self.notShuttingDown = True # TODO: allow shutdown of object
self.startMsgId = None self.startMsgId = None
self.eventLogger = eventLogger.getChild(f"{self.id}") self.eventLogger = eventLogger.getChild(f"{self.id}")
self.setStatus(self.STATE_GONE) self.setStatus(self.STATE_GONE)
self.requireRestartAfterStop = None self.requireRestartAfterStop = None
def __del__(self): def __del__(self):
self.logger.warn("Destroying hugvey object") self.logger.warn("Destroying hugvey object")
def getStatus(self): def getStatus(self):
return self.status return self.status
def setStatus(self, status): def setStatus(self, status):
self.status = status self.status = status
lightOn = status in [self.STATE_AVAILABLE, self.STATE_PAUSE] lightOn = status in [self.STATE_AVAILABLE, self.STATE_PAUSE]
self.setLightStatus(lightOn) self.setLightStatus(lightOn)
self.eventLogger.info(f"status: {self.status}") self.eventLogger.info(f"status: {self.status}")
def config(self, hostname, ip): def config(self, hostname, ip):
self.ip = ip self.ip = ip
self.hostname = hostname self.hostname = hostname
@ -463,7 +464,7 @@ class HugveyState(object):
else: else:
self.logger.info( self.logger.info(
f"Hugvey {self.id} at {self.ip}, host: {self.hostname}") f"Hugvey {self.id} at {self.ip}, host: {self.hostname}")
if self.status == self.STATE_GONE: if self.status == self.STATE_GONE:
# turn on :-) # turn on :-)
self.setStatus(self.STATE_BLOCKED) self.setStatus(self.STATE_BLOCKED)
@ -496,7 +497,7 @@ class HugveyState(object):
self.logger.exception(e) self.logger.exception(e)
self.logger.critical(f"Hugvey crash") self.logger.critical(f"Hugvey crash")
self.eventLogger.critical(f"error: {e}") self.eventLogger.critical(f"error: {e}")
# restart # restart
# TODO: test proper functioning # TODO: test proper functioning
self.shutdown() self.shutdown()
@ -510,18 +511,18 @@ class HugveyState(object):
else: else:
# Allow for both the Hugvey Command, or the Story handle the event. # Allow for both the Hugvey Command, or the Story handle the event.
self.loop.call_soon_threadsafe(self._queueEvent, msg) self.loop.call_soon_threadsafe(self._queueEvent, msg)
def _queueEvent(self, msg): def _queueEvent(self, msg):
""" """
Put event in both the event loop for the story as well as the Hugvey State handler Put event in both the event loop for the story as well as the Hugvey State handler
""" """
self.logger.debug(f"Queue event in hugvey loop: {msg}") self.logger.debug(f"Queue event in hugvey loop: {msg}")
self.eventQueue.put_nowait(msg) self.eventQueue.put_nowait(msg)
# connection events don't need to go to the story # connection events don't need to go to the story
if msg['event'] == 'connection': if msg['event'] == 'connection':
return return
if self.story: if self.story:
self.story.events.append(msg) self.story.events.append(msg)
else: else:
@ -538,7 +539,7 @@ class HugveyState(object):
self.logger.error("Hugvey did not send heartbeat.") self.logger.error("Hugvey did not send heartbeat.")
self.gone() self.gone()
continue continue
self.logger.debug("Received: {}".format(event)) self.logger.debug("Received: {}".format(event))
if event['event'] == 'connection': if event['event'] == 'connection':
# 'event': 'connection', # 'event': 'connection',
@ -546,11 +547,11 @@ class HugveyState(object):
# 'host': socket.gethostname(), # 'host': socket.gethostname(),
# 'ip': self.getIp(), # 'ip': self.getIp(),
self.config(event['host'], event['ip']) self.config(event['host'], event['ip'])
if event['event'] == 'language': if event['event'] == 'language':
self.setLanguage(event['code']) self.setLanguage(event['code'])
if event['event'] == 'pause': if event['event'] == 'pause':
self.pause() self.pause()
if event['event'] == 'block': if event['event'] == 'block':
@ -563,7 +564,7 @@ class HugveyState(object):
self.story._finish() # finish story AND hugvey state self.story._finish() # finish story AND hugvey state
if event['event'] == 'resume': if event['event'] == 'resume':
self.resume() self.resume()
if event['event'] == 'change_language': if event['event'] == 'change_language':
self.setLanguage(event['lang_code']) self.setLanguage(event['lang_code'])
if event['event'] == 'change_light': if event['event'] == 'change_light':
@ -577,7 +578,7 @@ class HugveyState(object):
# self.restart() # self.restart()
if self.story is None: if self.story is None:
return return
self.startMsgId = event['msg_id'] self.startMsgId = event['msg_id']
self.logger.debug(f"Restart from {self.startMsgId}") self.logger.debug(f"Restart from {self.startMsgId}")
self.restart() self.restart()
@ -587,18 +588,18 @@ class HugveyState(object):
def setLanguage(self, language_code): def setLanguage(self, language_code):
if language_code not in self.command.languages: if language_code not in self.command.languages:
raise Exception("Invalid language {}".format(language_code)) raise Exception("Invalid language {}".format(language_code))
self.logger.info(f"set language: {language_code}") self.logger.info(f"set language: {language_code}")
self.language_code = language_code self.language_code = language_code
if self.google: if self.google:
self.google.setLanguage(language_code) self.google.setLanguage(language_code)
if self.isRunning.is_set(): if self.isRunning.is_set():
self.restart() self.restart()
# self.story.reset() # self.story.reset()
# self.story.setStoryData(self.command.languages[language_code]) # self.story.setStoryData(self.command.languages[language_code])
def pause(self): def pause(self):
self.logger.info('Pause') self.logger.info('Pause')
if self.google: if self.google:
@ -607,7 +608,7 @@ class HugveyState(object):
self.story.pause() self.story.pause()
self.isRunning.clear() self.isRunning.clear()
self.setStatus(self.STATE_PAUSE) self.setStatus(self.STATE_PAUSE)
def resume(self): def resume(self):
""" Start playing without reset""" """ Start playing without reset"""
self.logger.info('Resume') self.logger.info('Resume')
@ -617,14 +618,14 @@ class HugveyState(object):
self.story.resume() self.story.resume()
self.isRunning.set() self.isRunning.set()
self.setStatus(self.STATE_RUNNING) self.setStatus(self.STATE_RUNNING)
def restart(self): def restart(self):
"""Start playing with reset""" """Start playing with reset"""
self.logger.info('Restart') self.logger.info('Restart')
if self.story: if self.story:
self.story.stop() self.story.stop()
self.resume() self.resume()
def block(self): def block(self):
"""Block a hugvey""" """Block a hugvey"""
self.logger.info('block') self.logger.info('block')
@ -634,37 +635,37 @@ class HugveyState(object):
self.story.finish() self.story.finish()
self.isRunning.clear() self.isRunning.clear()
self.setStatus(self.STATE_BLOCKED) self.setStatus(self.STATE_BLOCKED)
def available(self): def available(self):
"""Put in available mode""" """Put in available mode"""
self.logger.info('Finish/Await') self.logger.info('Finish/Await')
self.pause() self.pause()
self.setStatus(self.STATE_AVAILABLE) self.setStatus(self.STATE_AVAILABLE)
def setLightStatus(self, on): def setLightStatus(self, on):
status = 1 if on else 0 status = 1 if on else 0
self.logger.log(LOG_BS, f"Send /hugvey {status}") self.logger.log(LOG_BS, f"Send /hugvey {status}")
self.command.commandLight('/hugvey', [self.lightId, status]) self.command.commandLight('/hugvey', [self.lightId, status])
def setLightId(self, id): def setLightId(self, id):
""" """
Connect hugvey to another light Connect hugvey to another light
""" """
self.lightId = id self.lightId = id
def gone(self): def gone(self):
'''Status to 'gone' as in, shutdown/crashed/whatever '''Status to 'gone' as in, shutdown/crashed/whatever
''' '''
self.pause() self.pause()
if self.story: if self.story:
self.story.stop() self.story.stop()
self.logger.warn('Gone') self.logger.warn('Gone')
self.eventLogger.warn("Gone") self.eventLogger.warn("Gone")
self.isConfigured = None self.isConfigured = None
self.setStatus(self.STATE_GONE) self.setStatus(self.STATE_GONE)
def shutdown(self, definitive = False): def shutdown(self, definitive = False):
self.logger.info(f"Start shutdown sequence {definitive}") self.logger.info(f"Start shutdown sequence {definitive}")
self.eventLogger.critical(f"error: shutting down") self.eventLogger.critical(f"error: shutting down")
@ -673,7 +674,7 @@ class HugveyState(object):
if self.story: if self.story:
self.story.shutdown() self.story.shutdown()
self.story = None self.story = None
# shutdown for stream consumers already ran. Only clear references # shutdown for stream consumers already ran. Only clear references
if self.google: if self.google:
self.google = None self.google = None
@ -681,14 +682,14 @@ class HugveyState(object):
self.player = None self.player = None
if self.recorder: if self.recorder:
self.recorder = None self.recorder = None
if self.requireRestartAfterStop is None: if self.requireRestartAfterStop is None:
# prevent double setting of the same variable # prevent double setting of the same variable
# first call sometimes triggers second # first call sometimes triggers second
self.requireRestartAfterStop = not definitive self.requireRestartAfterStop = not definitive
self.notShuttingDown = False self.notShuttingDown = False
async def playStory(self): async def playStory(self):
while self.notShuttingDown: while self.notShuttingDown:
@ -706,13 +707,13 @@ class HugveyState(object):
self.logger.warn(f"Starting from {startMsgId}") self.logger.warn(f"Starting from {startMsgId}")
if not self.streamer: if not self.streamer:
await asyncio.sleep(1) await asyncio.sleep(1)
self.streamer.triggerStart() self.streamer.triggerStart()
self.story.setStoryData(self.command.languages[self.language_code]) self.story.setStoryData(copy.deepcopy(self.command.languages[self.language_code]))
self.setLightStatus(False) self.setLightStatus(False)
await self.story.run(startMsgId) await self.story.run(startMsgId)
# self.story = None # self.story = None
def getStreamer(self): def getStreamer(self):
if not self.streamer: if not self.streamer:
self.streamer = AudioStreamer( self.streamer = AudioStreamer(
@ -720,19 +721,19 @@ class HugveyState(object):
self.ip, self.ip,
int(self.command.config['voice']['port']) + self.id, int(self.command.config['voice']['port']) + self.id,
self.id) 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")
self.player = Player( self.player = Player(
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)
if self.command.config['voice']['record_dir']: if self.command.config['voice']['record_dir']:
self.logger.warn("Record Audio of conversation") self.logger.warn("Record Audio of conversation")
self.recorder = Recorder( self.id, self.recorder = Recorder( self.id,
self.command.config['voice']['src_rate'], self.command.config['voice']['record_dir']) self.command.config['voice']['src_rate'], self.command.config['voice']['record_dir'])
self.streamer.addConsumer(self.recorder) self.streamer.addConsumer(self.recorder)
self.logger.debug("Start Speech") self.logger.debug("Start Speech")
self.google = GoogleVoiceClient( self.google = GoogleVoiceClient(
hugvey=self, hugvey=self,
@ -747,7 +748,7 @@ class HugveyState(object):
''' '''
Start the audio streamer service Start the audio streamer service
''' '''
self.logger.debug("Start audio loop") self.logger.debug("Start audio loop")
while self.notShuttingDown: while self.notShuttingDown:

View file

@ -1,6 +1,6 @@
apt-get update apt-get update
apt-get install -y munin-node bc supervisor libsox-fmt-pulse apt-get install -y munin-node bc supervisor
cp installation/rpi-internal-temp /usr/share/munin/plugins cp installation/rpi-internal-temp /usr/share/munin/plugins
ln -sf /usr/share/munin/plugins/rpi-internal-temp /etc/munin/plugins/rpi-internal-temp ln -sf /usr/share/munin/plugins/rpi-internal-temp /etc/munin/plugins/rpi-internal-temp
rm /etc/munin/plugins/irqstats rm /etc/munin/plugins/irqstats

View file

@ -7,7 +7,7 @@ voice:
port: 4444 port: 4444
chunk: 2972 chunk: 2972
google_credentials: "../test_googlespeech/My First Project-0c7833e0d5fa.json" google_credentials: "../test_googlespeech/My First Project-0c7833e0d5fa.json"
hugveys: 25 hugveys: 26
languages: languages:
- code: en-GB - code: en-GB
file: story_en.json file: story_en.json
@ -28,7 +28,7 @@ languages:
ms_lang: "fr-FR" ms_lang: "fr-FR"
web: web:
port: 8888 port: 8888
files_dir: "local/" files_dir: "local/"
light: light:
ip: "192.168.178.15" ip: "192.168.178.15"
port: 7400 port: 7400

View file

@ -18,60 +18,60 @@ class Timeline{
{content: '.', start: new Date(), type: 'point', group: 1} {content: '.', start: new Date(), type: 'point', group: 1}
]); ]);
console.log('init timeline'); console.log('init timeline');
let groups = []; let groups = [];
for(let hid = 1; hid<=this.count; hid++) { for(let hid = 1; hid<=this.count; hid++) {
groups.push({id: parseInt(hid), content: 'Hugvey #'+hid}); groups.push({id: parseInt(hid), content: 'Hugvey #'+hid});
this.eventDataSet.add({content: 'initiate', start: new Date(), type: 'point', group: parseInt(hid)}) this.eventDataSet.add({content: 'initiate', start: new Date(), type: 'point', group: parseInt(hid)})
} }
let dataGroups = new vis.DataSet(groups); let dataGroups = new vis.DataSet(groups);
let options = { let options = {
// 'rollingMode': {'follow': true, 'offset': .8 } // 'rollingMode': {'follow': true, 'offset': .8 }
}; };
console.log('groups', dataGroups, groups, options); console.log('groups', dataGroups, groups, options);
this.timeline = new vis.Timeline(this.el, this.eventDataSet, dataGroups, options); this.timeline = new vis.Timeline(this.el, this.eventDataSet, dataGroups, options);
let tl = this.timeline; let tl = this.timeline;
let startDate = new Date(); let startDate = new Date();
startDate.setMinutes(startDate.getMinutes()-1); startDate.setMinutes(startDate.getMinutes()-1);
let endDate = new Date(); let endDate = new Date();
endDate.setMinutes(endDate.getMinutes()+20); endDate.setMinutes(endDate.getMinutes()+20);
setTimeout(function(){ setTimeout(function(){
tl.setWindow(startDate, endDate); tl.setWindow(startDate, endDate);
}, 500); }, 500);
this.moveInterval = setInterval(function(){ this.moveInterval = setInterval(function(){
// skip movement if not visible // skip movement if not visible
tl.moveTo(new Date()); tl.moveTo(new Date());
}, 1000); }, 1000);
ws.addEventListener( 'message', this); ws.addEventListener( 'message', this);
} }
handleEvent(e) { handleEvent(e) {
console.log('handle', e, this); console.log('handle', e, this);
if(e.type == 'message') { if(e.type == 'message') {
this.wsOnMessage(e) this.wsOnMessage(e)
} }
} }
wsOnMessage(e) { wsOnMessage(e) {
let msg = JSON.parse( e.data ); let msg = JSON.parse( e.data );
if ( typeof msg['action'] === 'undefined' ) { if ( typeof msg['action'] === 'undefined' ) {
console.error( "not a valid message: " + e.data ); console.error( "not a valid message: " + e.data );
return; return;
} }
if(msg['action'] != 'log') { if(msg['action'] != 'log') {
return; return;
} }
console.debug(msg, this); console.debug(msg, this);
let hv_id = parseInt(msg['id']); let hv_id = parseInt(msg['id']);
// {'action': 'log', 'id':hugvey_id, 'type': items[0], 'info', 'args'} // {'action': 'log', 'id':hugvey_id, 'type': items[0], 'info', 'args'}
let d, parts; let d, parts;
@ -91,7 +91,7 @@ class Timeline{
this.eventDataSet.update(d); this.eventDataSet.update(d);
console.log('update', d); console.log('update', d);
} else { } else {
this.eventDataSet.add({id: mId, content: msgContent, title: `${msgContent} (${msgId})`, start: new Date(), group: hv_id, 'className': 'message'}); this.eventDataSet.add({id: mId, content: msgContent, title: `${msgContent} (${msgId})`, start: new Date(), group: hv_id, 'className': 'message'});
} }
break; break;
case 'speaking': case 'speaking':
@ -101,7 +101,7 @@ class Timeline{
let id = parts.shift(); let id = parts.shift();
let content = parts.join(' '); let content = parts.join(' ');
let scId = 'sc-'+id+'-'+hv_id; let scId = 'sc-'+id+'-'+hv_id;
if(info.startsWith('start')){ if(info.startsWith('start')){
this.eventDataSet.add({content: info, start: new Date(), type: 'point', group: hv_id, 'className': 'speech'}); this.eventDataSet.add({content: info, start: new Date(), type: 'point', group: hv_id, 'className': 'speech'});
} }
@ -115,7 +115,7 @@ class Timeline{
this.eventDataSet.update(d); this.eventDataSet.update(d);
} else { } else {
console.log('add'); console.log('add');
this.eventDataSet.add({id: scId, content: content, title: content, start: new Date(), group: hv_id, 'className': 'speech'}); this.eventDataSet.add({id: scId, content: content, title: content, start: new Date(), group: hv_id, 'className': 'speech'});
} }
} }
if(info.startsWith('end')){ if(info.startsWith('end')){
@ -125,7 +125,7 @@ class Timeline{
this.eventDataSet.update(d); this.eventDataSet.update(d);
} }
} }
break; break;
case 'story': case 'story':
// 'info': 'start'/'finished' // 'info': 'start'/'finished'
@ -147,4 +147,4 @@ class Timeline{
} }
} }
var tl = new Timeline(ws, document.getElementById('line'), 25); var tl = new Timeline(ws, document.getElementById('line'), 26);