isSophie checkbox for light, and lightmap which is stored acros runs
This commit is contained in:
parent
f232d89166
commit
e3481a58ad
9 changed files with 189 additions and 60 deletions
|
@ -77,6 +77,9 @@ class CentralCommand(object):
|
||||||
|
|
||||||
self.hugveyWarnings = {}
|
self.hugveyWarnings = {}
|
||||||
|
|
||||||
|
self.lightMapFile = os.path.join('state','lightMap.json')
|
||||||
|
self.lightMap = {}
|
||||||
|
|
||||||
eventLogger.addHandler(logging.handlers.QueueHandler(self.logQueue))
|
eventLogger.addHandler(logging.handlers.QueueHandler(self.logQueue))
|
||||||
|
|
||||||
def loadConfig(self, filename):
|
def loadConfig(self, filename):
|
||||||
|
@ -92,10 +95,10 @@ class CentralCommand(object):
|
||||||
self.config[arg] = getattr(self.args,arg)
|
self.config[arg] = getattr(self.args,arg)
|
||||||
|
|
||||||
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.loadLightMap()
|
||||||
|
|
||||||
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)
|
||||||
varDb = os.path.join(
|
varDb = os.path.join(
|
||||||
|
@ -134,6 +137,25 @@ class CentralCommand(object):
|
||||||
with open(lang_filename, 'r') as fp:
|
with open(lang_filename, 'r') as fp:
|
||||||
self.languages[lang['code']] = json.load(fp)
|
self.languages[lang['code']] = json.load(fp)
|
||||||
|
|
||||||
|
def loadLightMap(self):
|
||||||
|
if os.path.exists(self.lightMapFile):
|
||||||
|
with open(self.lightMapFile) as fp:
|
||||||
|
lightMap = json.load(fp)
|
||||||
|
#json only has string keys, we want integers (not using pickle for human readability)
|
||||||
|
self.lightMap = {int(k): v for k,v in lightMap.items()}
|
||||||
|
logger.info(f"Loaded light mapping from {self.lightMapFile}")
|
||||||
|
for hv_id in self.hugvey_ids:
|
||||||
|
if hv_id not in self.lightMap:
|
||||||
|
print(hv_id, self.lightMap)
|
||||||
|
raise Exception("Invalid light map, not all hugveys are included. Remove lightMap.json")
|
||||||
|
else:
|
||||||
|
# by default each hv, has the same nr of light
|
||||||
|
self.lightMap = {id: id for id in self.hugvey_ids}
|
||||||
|
|
||||||
|
def saveLightMap(self):
|
||||||
|
with open(self.lightMapFile, 'w') as fp:
|
||||||
|
json.dump(self.lightMap, fp, indent=4, sort_keys=True)
|
||||||
|
logger.info(f"Wrote light mapping to {self.lightMapFile}")
|
||||||
|
|
||||||
def getHugveyStatus(self, hv_id, isSelected = False):
|
def getHugveyStatus(self, hv_id, isSelected = False):
|
||||||
status = {'id': hv_id}
|
status = {'id': hv_id}
|
||||||
|
@ -148,7 +170,7 @@ class CentralCommand(object):
|
||||||
|
|
||||||
#: :type hv: HugveyState
|
#: :type hv: HugveyState
|
||||||
status['status'] = hv.getStatus()
|
status['status'] = hv.getStatus()
|
||||||
status['light_on'] = bool(hv.lightStatus)
|
status['light'] = hv.lightTransitionStatus
|
||||||
status['language'] = hv.language_code
|
status['language'] = hv.language_code
|
||||||
status['light_id'] = hv.lightId
|
status['light_id'] = hv.lightId
|
||||||
status['available'] = hv.isAvailable()
|
status['available'] = hv.isAvailable()
|
||||||
|
@ -200,6 +222,16 @@ class CentralCommand(object):
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
def setLightForHugvey(self, hv_id, lightId):
|
||||||
|
if hv_id not in self.lightMap:
|
||||||
|
logger.critical(f"Try to configure light for non-existing Hugvey {hv_id}")
|
||||||
|
return
|
||||||
|
|
||||||
|
logger.info(f"Set light for hugvey: {hv_id} to {lightId}")
|
||||||
|
self.lightMap[hv_id] = lightId
|
||||||
|
self.hugveys[hv_id].setLightId(lightId)
|
||||||
|
self.saveLightMap()
|
||||||
|
|
||||||
def getStatusSummary(self, selected_ids = []):
|
def getStatusSummary(self, selected_ids = []):
|
||||||
status = {
|
status = {
|
||||||
'uptime': "-" if not self.start_time else (time.time() - self.start_time),
|
'uptime': "-" if not self.start_time else (time.time() - self.start_time),
|
||||||
|
@ -373,6 +405,7 @@ class CentralCommand(object):
|
||||||
while self.isRunning.is_set():
|
while self.isRunning.is_set():
|
||||||
logger.info(f'Instantiate hugvey #{hugvey_id}')
|
logger.info(f'Instantiate hugvey #{hugvey_id}')
|
||||||
h = HugveyState(hugvey_id, self)
|
h = HugveyState(hugvey_id, self)
|
||||||
|
h.setLightId(self.lightMap[hugvey_id])
|
||||||
# h.config(msg['host'], msg['ip'])
|
# h.config(msg['host'], msg['ip'])
|
||||||
self.hugveys[hugvey_id] = h
|
self.hugveys[hugvey_id] = h
|
||||||
r = h.run()
|
r = h.run()
|
||||||
|
@ -553,6 +586,7 @@ class HugveyState(object):
|
||||||
self.setStatus(self.STATE_GONE)
|
self.setStatus(self.STATE_GONE)
|
||||||
|
|
||||||
self.requireRestartAfterStop = None
|
self.requireRestartAfterStop = None
|
||||||
|
self.lightTransitionStatus = {'intensity': self.command.config['light']['off_intensity'], 'duration': self.command.config['light']['fade_duration_id'], 'isSophie': False}
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.logger.warn("Destroying hugvey object")
|
self.logger.warn("Destroying hugvey object")
|
||||||
|
@ -793,14 +827,16 @@ class HugveyState(object):
|
||||||
|
|
||||||
self.command.commandLight('/hugvey', [self.lightId, self.lightStatus])
|
self.command.commandLight('/hugvey', [self.lightId, self.lightStatus])
|
||||||
|
|
||||||
def transitionLight(self, intensity, duration):
|
def transitionLight(self, intensity, duration, isSophie = False):
|
||||||
"""
|
"""
|
||||||
Intensity: 0-255
|
Intensity: 0-255
|
||||||
duration: an integer between 0-92 indicating the lanbox fade times
|
duration: an integer between 0-92 indicating the lanbox fade times
|
||||||
|
The light fade in & out for Sophie (a moment in the story) are an override, so that
|
||||||
|
they come in even though all is out.
|
||||||
"""
|
"""
|
||||||
self.lightIntensity = intensity
|
self.lightTransitionStatus = {'intensity': intensity, 'duration': duration, 'isSophie': isSophie}
|
||||||
self.logger.debug(f"Send /hugvey_fade {self.lightIntensity} {duration}")
|
self.logger.debug(f"Send /hugvey_fade {intensity} {duration} {1 if isSophie else 0}")
|
||||||
self.command.commandLight('/hugvey_fade', [self.lightId, intensity, int(duration)])
|
self.command.commandLight('/hugvey_fade', [self.lightId, intensity, int(duration), 1 if isSophie else 0])
|
||||||
|
|
||||||
def setLightId(self, id):
|
def setLightId(self, id):
|
||||||
"""
|
"""
|
||||||
|
@ -890,8 +926,9 @@ class HugveyState(object):
|
||||||
|
|
||||||
if self.command.config['story']['loop']:
|
if self.command.config['story']['loop']:
|
||||||
if not self.blockRestart:
|
if not self.blockRestart:
|
||||||
self.logger.info("Loop story")
|
if self.notShuttingDown:
|
||||||
self.restart()
|
self.logger.info("Loop story")
|
||||||
|
self.restart()
|
||||||
else:
|
else:
|
||||||
self.logger.info("Don't loop on manual finish")
|
self.logger.info("Don't loop on manual finish")
|
||||||
|
|
||||||
|
@ -914,7 +951,7 @@ class HugveyState(object):
|
||||||
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.info("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.command.config['voice']['record_voice'] if 'record_voice' in self.command.config['voice'] else False)
|
self.command.config['voice']['record_voice'] if 'record_voice' in self.command.config['voice'] else False)
|
||||||
|
|
|
@ -169,8 +169,9 @@ def getWebSocketHandler(central_command):
|
||||||
central_command.setLoopTime(seconds)
|
central_command.setLoopTime(seconds)
|
||||||
|
|
||||||
def msgChangeLightId(self, hv_id, lightId):
|
def msgChangeLightId(self, hv_id, lightId):
|
||||||
if central_command.hugveys[hv_id].eventQueue:
|
central_command.setLightForHugvey(hv_id, lightId)
|
||||||
central_command.hugveys[hv_id].eventQueue.put_nowait({'event': 'change_light', 'light_id': lightId})
|
# if central_command.hugveys[hv_id].eventQueue:
|
||||||
|
# central_command.hugveys[hv_id].eventQueue.put_nowait({'event': 'change_light', 'light_id': lightId})
|
||||||
|
|
||||||
def msgChangeLightStatus(self, hv_id, status):
|
def msgChangeLightStatus(self, hv_id, status):
|
||||||
if central_command.hugveys[hv_id].eventQueue:
|
if central_command.hugveys[hv_id].eventQueue:
|
||||||
|
|
|
@ -1166,14 +1166,19 @@ class Configuration(object):
|
||||||
time_factor = 1
|
time_factor = 1
|
||||||
light0_intensity = 0
|
light0_intensity = 0
|
||||||
light0_fade = 30. # fade duration in seconds
|
light0_fade = 30. # fade duration in seconds
|
||||||
|
light0_isSophie = False
|
||||||
light1_intensity = 150
|
light1_intensity = 150
|
||||||
light1_fade = 10.
|
light1_fade = 10.
|
||||||
|
light1_isSophie = False
|
||||||
light2_intensity = 75
|
light2_intensity = 75
|
||||||
light2_fade = 10.
|
light2_fade = 10.
|
||||||
|
light2_isSophie = False
|
||||||
light3_intensity = 150
|
light3_intensity = 150
|
||||||
light3_fade = 10.
|
light3_fade = 10.
|
||||||
|
light3_isSophie = False
|
||||||
light4_intensity = 150
|
light4_intensity = 150
|
||||||
light4_fade = 10.
|
light4_fade = 10.
|
||||||
|
light4_isSophie = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def initFromJson(configClass, data, story):
|
def initFromJson(configClass, data, story):
|
||||||
|
@ -1187,7 +1192,8 @@ class Configuration(object):
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
l.append({
|
l.append({
|
||||||
'intensity': int(c[f"light{i}_intensity"]),
|
'intensity': int(c[f"light{i}_intensity"]),
|
||||||
'fade': float(c[f"light{i}_fade"])
|
'fade': float(c[f"light{i}_fade"]),
|
||||||
|
'isSophie': float(c[f"light{i}_isSophie"])
|
||||||
})
|
})
|
||||||
return l
|
return l
|
||||||
|
|
||||||
|
@ -1783,7 +1789,7 @@ class Story(object):
|
||||||
# Test stability of Central Command with deliberate crash
|
# Test stability of Central Command with deliberate crash
|
||||||
# if self.timer.getElapsed() > 10:
|
# if self.timer.getElapsed() > 10:
|
||||||
# raise Exception("Test exception")
|
# raise Exception("Test exception")
|
||||||
if not self.timer.hasMark('state_save') or self.timer.getElapsed('state_save') > 45:
|
if not self.timer.hasMark('state_save') or self.timer.getElapsed('state_save') > 30:
|
||||||
self.storeState()
|
self.storeState()
|
||||||
self.timer.setMark('state_save')
|
self.timer.setMark('state_save')
|
||||||
|
|
||||||
|
@ -1891,7 +1897,7 @@ class Story(object):
|
||||||
preset = self.configuration.getLightPresets()[presetNr]
|
preset = self.configuration.getLightPresets()[presetNr]
|
||||||
self.currentLightPresetNr = presetNr
|
self.currentLightPresetNr = presetNr
|
||||||
|
|
||||||
self.hugvey.transitionLight(preset['intensity'], preset['fade'])
|
self.hugvey.transitionLight(preset['intensity'], preset['fade'], preset['isSophie'])
|
||||||
|
|
||||||
def getCurrentDirections(self):
|
def getCurrentDirections(self):
|
||||||
if self.currentMessage.id not in self.directionsPerMsg:
|
if self.currentMessage.id not in self.directionsPerMsg:
|
||||||
|
@ -2082,6 +2088,7 @@ class Story(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def hugveyHasSavedState(cls, hv_id):
|
def hugveyHasSavedState(cls, hv_id):
|
||||||
|
# print(os.path.exists(cls.getStateFilename(hv_id)), cls.getStateFilename(hv_id))
|
||||||
return os.path.exists(cls.getStateFilename(hv_id))
|
return os.path.exists(cls.getStateFilename(hv_id))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -2095,6 +2102,7 @@ class Story(object):
|
||||||
story.logger = mainLogger.getChild(f"{story.hugvey.id}").getChild("story")
|
story.logger = mainLogger.getChild(f"{story.hugvey.id}").getChild("story")
|
||||||
# TODO: this is not really working because it is overridden by the set-status later.
|
# TODO: this is not really working because it is overridden by the set-status later.
|
||||||
# story.hugvey.setLightStatus(story.lightStateSave)
|
# story.hugvey.setLightStatus(story.lightStateSave)
|
||||||
|
story.logger.critical(f"Light preset {story.currentLightPresetNr}")
|
||||||
if story.currentLightPresetNr is not None:
|
if story.currentLightPresetNr is not None:
|
||||||
story.fadeLightPreset(story.currentLightPresetNr)
|
story.fadeLightPreset(story.currentLightPresetNr)
|
||||||
return story
|
return story
|
||||||
|
|
|
@ -60,6 +60,12 @@ if __name__ == '__main__':
|
||||||
rootLogger.addHandler(socket_handler)
|
rootLogger.addHandler(socket_handler)
|
||||||
logger.info("Start server")
|
logger.info("Start server")
|
||||||
|
|
||||||
command = CentralCommand(args=args, debug_mode=args.verbose > 0)
|
|
||||||
command.loadConfig(args.config)
|
try:
|
||||||
command.start()
|
print('\33]0;Hugvey server\a', end='', flush=True)
|
||||||
|
command = CentralCommand(args=args, debug_mode=args.verbose > 0)
|
||||||
|
command.loadConfig(args.config)
|
||||||
|
command.start()
|
||||||
|
finally:
|
||||||
|
# reset terminal title
|
||||||
|
print('\33]0;\a', end='', flush=True)
|
||||||
|
|
|
@ -125,7 +125,10 @@ img.icon {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 5px;
|
left: 5px;
|
||||||
top: 5px; }
|
top: 5px;
|
||||||
|
font-size: 150%; }
|
||||||
|
#status .hugvey h1 .light_id-hv_id {
|
||||||
|
font-size: 75%; }
|
||||||
#status .hugvey .status {
|
#status .hugvey .status {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: gray;
|
color: gray;
|
||||||
|
|
6
www/js/crel.min.js
vendored
6
www/js/crel.min.js
vendored
|
@ -1,5 +1,11 @@
|
||||||
!function(n,e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):n.crel=e()}(this,function(){function n(a){var d,s=arguments,p=s[1],y=2,m=s.length,x=n[o];if(a=n[u](a)?a:c.createElement(a),m>1){if((!e(p,r)||n[f](p)||Array.isArray(p))&&(--y,p=null),m-y==1&&e(s[y],"string"))a.textContent=s[y];else for(;y<m;++y)null!==(d=s[y])&&l(a,d);for(var v in p)if(x[v]){var A=x[v];e(A,t)?A(a,p[v]):a[i](A,p[v])}else e(p[v],t)?a[v]=p[v]:a[i](v,p[v])}return a}var e=function(n,e){return typeof n===e},t="function",r="object",i="setAttribute",o="attrMap",f="isNode",u="isElement",c=document,a=function(n){return n instanceof Node},d=function(n){return n instanceof Element},l=function(e,t){if(Array.isArray(t))return void t.map(function(n){l(e,n)});n[f](t)||(t=c.createTextNode(t)),e.appendChild(t)};return n[o]={},n[u]=d,n[f]=a,e(Proxy,"undefined")||(n.proxy=new Proxy(n,{get:function(e,t){return!(t in n)&&(n[t]=n.bind(null,t)),n[t]}})),n});
|
!function(n,e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):n.crel=e()}(this,function(){function n(a){var d,s=arguments,p=s[1],y=2,m=s.length,x=n[o];if(a=n[u](a)?a:c.createElement(a),m>1){if((!e(p,r)||n[f](p)||Array.isArray(p))&&(--y,p=null),m-y==1&&e(s[y],"string"))a.textContent=s[y];else for(;y<m;++y)null!==(d=s[y])&&l(a,d);for(var v in p)if(x[v]){var A=x[v];e(A,t)?A(a,p[v]):a[i](A,p[v])}else e(p[v],t)?a[v]=p[v]:a[i](v,p[v])}return a}var e=function(n,e){return typeof n===e},t="function",r="object",i="setAttribute",o="attrMap",f="isNode",u="isElement",c=document,a=function(n){return n instanceof Node},d=function(n){return n instanceof Element},l=function(e,t){if(Array.isArray(t))return void t.map(function(n){l(e,n)});n[f](t)||(t=c.createTextNode(t)),e.appendChild(t)};return n[o]={},n[u]=d,n[f]=a,e(Proxy,"undefined")||(n.proxy=new Proxy(n,{get:function(e,t){return!(t in n)&&(n[t]=n.bind(null,t)),n[t]}})),n});
|
||||||
|
|
||||||
|
// for input type checkbox, map value to a checkbox
|
||||||
|
crel.attrMap['checked_value'] = function(element, value) {
|
||||||
|
if(value) {
|
||||||
|
element.checked = 'checked';
|
||||||
|
}
|
||||||
|
};
|
||||||
crel.attrMap['on'] = function(element, value) {
|
crel.attrMap['on'] = function(element, value) {
|
||||||
for (var eventName in value) {
|
for (var eventName in value) {
|
||||||
element.addEventListener(eventName, value[eventName]);
|
element.addEventListener(eventName, value[eventName]);
|
||||||
|
|
|
@ -1137,6 +1137,19 @@ class Graph {
|
||||||
'value': this.configuration.hasOwnProperty('light0_fade') ? this.configuration.light0_fade: ""
|
'value': this.configuration.hasOwnProperty('light0_fade') ? this.configuration.light0_fade: ""
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
crel(
|
||||||
|
'label',
|
||||||
|
"Is Sophie: ",
|
||||||
|
crel('input', {
|
||||||
|
'type': 'checkbox',
|
||||||
|
'checked_value': this.configuration.hasOwnProperty('light0_isSophie') ? this.configuration.light0_isSophie: false,
|
||||||
|
'on': {
|
||||||
|
'change': function(e){
|
||||||
|
panopticon.graph.configuration['light0_isSophie'] = e.target.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
crel('h2', 'Light fade setting #1'),
|
crel('h2', 'Light fade setting #1'),
|
||||||
crel(
|
crel(
|
||||||
'label',
|
'label',
|
||||||
|
@ -1169,6 +1182,19 @@ class Graph {
|
||||||
'value': this.configuration.hasOwnProperty('light1_fade') ? this.configuration.light1_fade: ""
|
'value': this.configuration.hasOwnProperty('light1_fade') ? this.configuration.light1_fade: ""
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
crel(
|
||||||
|
'label',
|
||||||
|
"Is Sophie: ",
|
||||||
|
crel('input', {
|
||||||
|
'type': 'checkbox',
|
||||||
|
'checked_value': this.configuration.hasOwnProperty('light1_isSophie') ? this.configuration.light1_isSophie: false,
|
||||||
|
'on': {
|
||||||
|
'change': function(e){
|
||||||
|
panopticon.graph.configuration['light1_isSophie'] = e.target.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
crel('h2', 'Light fade setting #2'),
|
crel('h2', 'Light fade setting #2'),
|
||||||
crel(
|
crel(
|
||||||
'label',
|
'label',
|
||||||
|
@ -1201,6 +1227,19 @@ class Graph {
|
||||||
'value': this.configuration.hasOwnProperty('light2_fade') ? this.configuration.light2_fade: ""
|
'value': this.configuration.hasOwnProperty('light2_fade') ? this.configuration.light2_fade: ""
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
crel(
|
||||||
|
'label',
|
||||||
|
"Is Sophie: ",
|
||||||
|
crel('input', {
|
||||||
|
'type': 'checkbox',
|
||||||
|
'checked_value': this.configuration.hasOwnProperty('light2_isSophie') ? this.configuration.light2_isSophie: false,
|
||||||
|
'on': {
|
||||||
|
'change': function(e){
|
||||||
|
panopticon.graph.configuration['light2_isSophie'] = e.target.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
crel('h2', 'Light fade setting #3'),
|
crel('h2', 'Light fade setting #3'),
|
||||||
crel(
|
crel(
|
||||||
'label',
|
'label',
|
||||||
|
@ -1233,6 +1272,19 @@ class Graph {
|
||||||
'value': this.configuration.hasOwnProperty('light3_fade') ? this.configuration.light3_fade: ""
|
'value': this.configuration.hasOwnProperty('light3_fade') ? this.configuration.light3_fade: ""
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
crel(
|
||||||
|
'label',
|
||||||
|
"Is Sophie: ",
|
||||||
|
crel('input', {
|
||||||
|
'type': 'checkbox',
|
||||||
|
'checked_value': this.configuration.hasOwnProperty('light3_isSophie') ? this.configuration.light3_isSophie: false,
|
||||||
|
'on': {
|
||||||
|
'change': function(e){
|
||||||
|
panopticon.graph.configuration['light3_isSophie'] = e.target.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
crel('h2', 'Light fade setting #4'),
|
crel('h2', 'Light fade setting #4'),
|
||||||
crel(
|
crel(
|
||||||
'label',
|
'label',
|
||||||
|
@ -1264,7 +1316,20 @@ class Graph {
|
||||||
},
|
},
|
||||||
'value': this.configuration.hasOwnProperty('light4_fade') ? this.configuration.light4_fade: ""
|
'value': this.configuration.hasOwnProperty('light4_fade') ? this.configuration.light4_fade: ""
|
||||||
})
|
})
|
||||||
)
|
),
|
||||||
|
crel(
|
||||||
|
'label',
|
||||||
|
"Is Sophie: ",
|
||||||
|
crel('input', {
|
||||||
|
'type': 'checkbox',
|
||||||
|
'checked_value': this.configuration.hasOwnProperty('light4_isSophie') ? this.configuration.light4_isSophie: false,
|
||||||
|
'on': {
|
||||||
|
'change': function(e){
|
||||||
|
panopticon.graph.configuration['light4_isSophie'] = e.target.checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
document.getElementById("interface").appendChild(configEl);
|
document.getElementById("interface").appendChild(configEl);
|
||||||
|
|
|
@ -23,56 +23,55 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class='hugvey' v-for="hv in hugveys"
|
<div class='hugvey' v-for="hv in hugveys"
|
||||||
:class="[{'hugvey--on': hv.status != 'off'},'hugvey--' + hv.status, 'hugvey--light-' + hv.light_on]"
|
:class="[{'hugvey--on': hv.status != 'off'},'hugvey--' + hv.status]"
|
||||||
@click="showHugvey(hv)"
|
@click="showHugvey(hv)"
|
||||||
>
|
>
|
||||||
<h1>
|
<h1>
|
||||||
{{ hv.light_id }} <span v-if="hv.id != hv.light_id">(#{{hv.id}})</span>
|
{{ hv.light_id }} <span class='light_id-hv_id' v-if="hv.id != hv.light_id">(#{{hv.id}})</span>
|
||||||
</h1>
|
</h1>
|
||||||
<div class='status'>{{ hv.status }}</div>
|
<div class='status'>{{ hv.status }}</div>
|
||||||
<div v-if="hv.status != 'off' && hv.status != 'gone' && hv.status != 'loading'">
|
<div v-if="hv.status != 'off' && hv.status != 'loading'">
|
||||||
<select v-model="hv.language" @change="change_lang(hv, hv.language)" v-on:click.stop>
|
<div v-if="hv.status != 'gone'">
|
||||||
<option v-for="lang in languages" :title="lang.file"
|
<select v-model="hv.language" @change="change_lang(hv, hv.language)" v-on:click.stop>
|
||||||
:value="lang.code">
|
<option v-for="lang in languages" :title="lang.file"
|
||||||
<span :class="['flag-icon', lang.code]"></span>
|
:value="lang.code">
|
||||||
{{lang.code}}
|
<span :class="['flag-icon', lang.code]"></span>
|
||||||
</option>
|
{{lang.code}}
|
||||||
</select>
|
</option>
|
||||||
{{ hv.language }}
|
</select>
|
||||||
|
{{ hv.language }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <div v-if="hv.awaiting != false"><img class='icon' :src="'/images/icon-finished.svg'" title="Finished"> {{timer(hv,
|
<!-- <div v-if="hv.awaiting != false"><img class='icon' :src="'/images/icon-finished.svg'" title="Finished"> {{timer(hv,
|
||||||
'finished')}}</div> -->
|
'finished')}}</div> -->
|
||||||
<div class='stats'>
|
<div class='stats'>
|
||||||
<div class='count' v-for="c, key in hv.counts">
|
<div class='count' v-for="c, key in hv.counts">
|
||||||
<img class='icon' :src="'/images/icon-' + key + '.svg'" :title="key">
|
<img class='icon' :src="'/images/icon-' + key + '.svg'" :title="key">
|
||||||
{{c}}
|
{{c}}
|
||||||
</div>
|
</div>
|
||||||
<div class='position'>
|
<div class='position'>
|
||||||
<img class='icon' src="/images/icon-position.svg" title="position">
|
<img class='icon' src="/images/icon-position.svg" title="position">
|
||||||
{{ hv.msg }}
|
{{ hv.msg }}
|
||||||
</div>
|
</div>
|
||||||
<div class='timer' v-if="hv.duration">
|
<div class='timer' v-if="hv.duration">
|
||||||
<img class='icon' src="/images/icon-clock.svg" title="timer">
|
<img class='icon' src="/images/icon-clock.svg" title="timer">
|
||||||
{{ timer(hv, 'duration') }}
|
{{ timer(hv, 'duration') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class='btn' v-if="hv.status == 'blocked'" @click.stop="unblock(hv)">Unblock</div>
|
||||||
|
<div class='btn' v-if="hv.status == 'available'" @click.stop="block(hv)">Block</div>
|
||||||
|
<div class='btn' v-if="hv.status == 'available' || hv.status =='blocked'" @click.stop="restart(hv)">Start</div>
|
||||||
|
<div class='btn' v-if="hv.status == 'running'" @click.stop="finish(hv)">Finish</div> <!-- to available state -->
|
||||||
|
<div class='btn' v-if="hv.status == 'running'" @click.stop="pause(hv)">Pause</div>
|
||||||
|
<div class='btn' v-if="hv.status == 'paused'" @click.stop="resume(hv)">Resume</div>
|
||||||
|
|
||||||
|
<div class='btn' v-if="(hv.status == 'available' || hv.status == 'blocked') && hv.has_state" @click.stop="resume(hv)">Resume from save</div>
|
||||||
</div>
|
</div>
|
||||||
<div class='btn' v-if="hv.status == 'blocked'" @click.stop="unblock(hv)">Unblock</div>
|
|
||||||
<div class='btn' v-if="hv.status == 'available'" @click.stop="block(hv)">Block</div>
|
|
||||||
<div class='btn' v-if="hv.status == 'available' || hv.status =='blocked'" @click.stop="restart(hv)">Start</div>
|
|
||||||
<div class='btn' v-if="hv.status == 'running'" @click.stop="finish(hv)">Finish</div> <!-- to available state -->
|
|
||||||
<div class='btn' v-if="hv.status == 'running'" @click.stop="pause(hv)">Pause</div>
|
|
||||||
<div class='btn' v-if="hv.status == 'paused'" @click.stop="resume(hv)">Resume</div>
|
|
||||||
|
|
||||||
<div class='btn' v-if="(hv.status == 'available' || hv.status == 'blocked') && hv.has_state" @click.stop="resume(hv)">Resume from save</div>
|
|
||||||
<!-- <div class='light'>
|
|
||||||
{{ hv.light }}
|
|
||||||
</div> -->
|
|
||||||
<div class='light'>
|
<div class='light'>
|
||||||
Light:
|
Light:
|
||||||
<input type="number" step="1" :value="hv.light_id" @change="change_light" :data-hvid="hv.id" v-on:click.stop>
|
<input type="number" step="1" :value="hv.light_id" @change="change_light" :data-hvid="hv.id" v-on:click.stop>
|
||||||
<input type="checkbox" v-model="hv.light_on" @change="change_light_status" :data-hvid="hv.id" v-on:click.stop>
|
<div>Intensity: {{hv.light['intensity']}}, Fade #{{hv.light['duration']}} <span v-if="hv.light['isSophie']">(sophie)</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -172,6 +172,10 @@ img.icon{
|
||||||
left: 5px;
|
left: 5px;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
font-size:150%;
|
font-size:150%;
|
||||||
|
|
||||||
|
.light_id-hv_id{
|
||||||
|
font-size:75%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.status{
|
.status{
|
||||||
|
|
Loading…
Reference in a new issue