Support for subscribe-once/unsubscribe frontend events mechanisms

This commit is contained in:
Fabio Manganiello 2020-12-15 00:01:28 +01:00
parent 0db997c6a0
commit 5d4f4b0378
46 changed files with 173 additions and 75 deletions

View file

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-014e8b04.542f4068.css" rel="prefetch"><link href="/static/css/chunk-16a3f845.1df61c27.css" rel="prefetch"><link href="/static/css/chunk-24ff873d.5ef32028.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.431b3300.css" rel="prefetch"><link href="/static/css/chunk-5710a9bc.763b29ed.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.495b15c5.css" rel="prefetch"><link href="/static/css/chunk-ac6aae98.f24d8093.css" rel="prefetch"><link href="/static/css/chunk-e8078048.6c400707.css" rel="prefetch"><link href="/static/js/chunk-014e8b04.7f400c2d.js" rel="prefetch"><link href="/static/js/chunk-16a3f845.59b58d41.js" rel="prefetch"><link href="/static/js/chunk-24ff873d.f955ad3b.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.ec2fb649.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.6f0e4975.js" rel="prefetch"><link href="/static/js/chunk-5710a9bc.47bb3f2d.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.8fc4fd3a.js" rel="prefetch"><link href="/static/js/chunk-ac6aae98.04b7413c.js" rel="prefetch"><link href="/static/js/chunk-e8078048.e668de5f.js" rel="prefetch"><link href="/static/css/app.5408c936.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.fd969252.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.6eaf6fa5.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.5408c936.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.6eaf6fa5.js"></script><script src="/static/js/app.fd969252.js"></script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-24ff873d.5ef32028.css" rel="prefetch"><link href="/static/css/chunk-35b45d59.bea59a51.css" rel="prefetch"><link href="/static/css/chunk-45939517.1062df39.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.431b3300.css" rel="prefetch"><link href="/static/css/chunk-53360c78.2281ab32.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.495b15c5.css" rel="prefetch"><link href="/static/css/chunk-6fa461b6.1fb05517.css" rel="prefetch"><link href="/static/css/chunk-e8078048.6c400707.css" rel="prefetch"><link href="/static/js/chunk-24ff873d.f955ad3b.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.8d32d3ba.js" rel="prefetch"><link href="/static/js/chunk-35b45d59.d541d43f.js" rel="prefetch"><link href="/static/js/chunk-45939517.38162e50.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.6f0e4975.js" rel="prefetch"><link href="/static/js/chunk-53360c78.54e2e626.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.8fc4fd3a.js" rel="prefetch"><link href="/static/js/chunk-6fa461b6.d6fffa0d.js" rel="prefetch"><link href="/static/js/chunk-e8078048.e668de5f.js" rel="prefetch"><link href="/static/css/app.5408c936.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.41ee3441.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.1eac7b43.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.5408c936.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.1eac7b43.js"></script><script src="/static/js/app.41ee3441.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-45939517"],{"1cb0":function(e,t,s){"use strict";s("5eaa")},"2e0b":function(e,t,s){"use strict";s("e458")},3737:function(e,t,s){"use strict";s.r(t);s("b64b");var a=s("7a23"),n=Object(a["J"])("data-v-d6e48dfa");Object(a["u"])("data-v-d6e48dfa");var r={class:"date-time-weather"},i={class:"row date-time-container"},o={class:"row weather-container"},c={class:"row sensors-container"},u={key:0,class:"row"},h={class:"col-3"},d=Object(a["h"])("div",{class:"col-6"}," ",-1),l={class:"col-3"};Object(a["s"])();var m=n((function(e,t,s,n,m,b){var f=Object(a["z"])("DateTime"),w=Object(a["z"])("Weather"),j=Object(a["z"])("Sensor");return Object(a["r"])(),Object(a["e"])("div",r,[Object(a["h"])("div",i,[b._showDate||b._showTime?(Object(a["r"])(),Object(a["e"])(f,{key:0,"show-date":b._showDate,"show-time":b._showTime,"show-seconds":b._showSeconds,animate:s.animate},null,8,["show-date","show-time","show-seconds","animate"])):Object(a["f"])("",!0)]),Object(a["h"])("div",o,[s.showWeather?(Object(a["r"])(),Object(a["e"])(w,{key:0,"show-summary":b._showSummary,animate:b._animate,"icon-size":s.iconSize,"refresh-seconds":s.weatherRefreshSeconds},null,8,["show-summary","animate","icon-size","refresh-seconds"])):Object(a["f"])("",!0)]),Object(a["h"])("div",c,[b._showSensors&&Object.keys(e.sensors).length?(Object(a["r"])(),Object(a["e"])("div",u,[Object(a["h"])("div",h,[null!=e.sensors.temperature?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-thermometer-half",value:e.sensors.temperature,unit:"°"},null,8,["value"])):Object(a["f"])("",!0)]),d,Object(a["h"])("div",l,[null!=e.sensors.humidity?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-tint",value:e.sensors.humidity,unit:"%"},null,8,["value"])):Object(a["f"])("",!0)])])):Object(a["f"])("",!0)])])})),b=(s("a9e3"),s("3e54")),f=s("365a"),w=s("5b43"),j=(s("b0c0"),Object(a["J"])("data-v-1efb373e"));Object(a["u"])("data-v-1efb373e");var O={class:"sensor"},p={key:0,class:"label-container col-6"},v={class:"value-container col-6"};Object(a["s"])();var y=j((function(e,t,s,n,r,i){return Object(a["r"])(),Object(a["e"])("div",O,[s.iconClass||s.name?(Object(a["r"])(),Object(a["e"])("div",p,[s.iconClass?(Object(a["r"])(),Object(a["e"])("i",{key:0,class:s.iconClass},null,2)):s.name?(Object(a["r"])(),Object(a["e"])("span",{key:1,textContent:Object(a["C"])(s.name)},null,8,["textContent"])):Object(a["f"])("",!0)])):Object(a["f"])("",!0),Object(a["h"])("div",v,[Object(a["h"])("span",{class:"value",textContent:Object(a["C"])(i._value)},null,8,["textContent"])])])})),S=(s("99af"),s("b680"),{name:"Sensor",props:{iconClass:{type:String,required:!1},name:{type:String,required:!1},value:{required:!1},unit:{type:String,required:!1},decimals:{type:Number,required:!1,default:1},isBoolean:{type:Boolean,required:!1,default:!1}},computed:{_value:function(){if(null==this.value)return"N/A";if(this.isBoolean)return this.parseBoolean(this.value);var e=parseFloat(this.value);return null!=this.decimals&&(e=e.toFixed(this.decimals)),this.unit&&(e="".concat(e).concat(this.unit)),e}}});s("2e0b");S.render=y,S.__scopeId="data-v-1efb373e";var _=S,q={name:"DateTimeWeather",mixins:[b["a"]],components:{Sensor:_,DateTime:f["default"],Weather:w["default"]},props:{animate:{required:!1,default:!0},iconSize:{type:Number,required:!1,default:50},showDate:{required:!1,default:!0},showTime:{required:!1,default:!0},showWeather:{required:!1,default:!0},showSummary:{required:!1,default:!0},showSensors:{required:!1,default:!0},showSeconds:{required:!1,default:!0},sensorTemperatureAttr:{type:String,required:!1,default:"temperature"},sensorHumidityAttr:{type:String,required:!1,default:"humidity"},weatherRefreshSeconds:{type:Number,required:!1,default:900}},computed:{_showDate:function(){return this.parseBoolean(this.showDate)},_showTime:function(){return this.parseBoolean(this.showTime)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)},_showWeather:function(){return this.parseBoolean(this.showWeather)},_showSummary:function(){return this.parseBoolean(this.showSummary)},_showSensors:function(){return this.parseBoolean(this.showSensors)},_animate:function(){return this.parseBoolean(this.animate)}},data:function(){return{sensors:{}}},methods:{onSensorData:function(e){this.sensorTemperatureAttr in e.data&&(this.sensors.temperature=e.data.temperature),this.sensorHumidityAttr in e.data&&(this.sensors.humidity=e.data.humidity)}},mounted:function(){this.subscribe(this.onSensorData,null,"platypush.message.event.sensor.SensorDataChangeEvent")}};s("1cb0");q.render=m,q.__scopeId="data-v-d6e48dfa";t["default"]=q},"5eaa":function(e,t,s){},e458:function(e,t,s){}}]);
//# sourceMappingURL=chunk-45939517.38162e50.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,2 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5710a9bc"],{"2e0b":function(e,t,s){"use strict";s("e458")},3737:function(e,t,s){"use strict";s.r(t);s("b64b");var a=s("7a23"),n=Object(a["J"])("data-v-6bc0bd70");Object(a["u"])("data-v-6bc0bd70");var r={class:"date-time-weather"},i={class:"row date-time-container"},o={class:"row weather-container"},c={class:"row sensors-container"},u={key:0,class:"row"},d={class:"col-3"},h=Object(a["h"])("div",{class:"col-6"}," ",-1),l={class:"col-3"};Object(a["s"])();var b=n((function(e,t,s,n,b,m){var f=Object(a["z"])("DateTime"),w=Object(a["z"])("Weather"),j=Object(a["z"])("Sensor");return Object(a["r"])(),Object(a["e"])("div",r,[Object(a["h"])("div",i,[m._showDate||m._showTime?(Object(a["r"])(),Object(a["e"])(f,{key:0,"show-date":m._showDate,"show-time":m._showTime,"show-seconds":m._showSeconds,animate:s.animate},null,8,["show-date","show-time","show-seconds","animate"])):Object(a["f"])("",!0)]),Object(a["h"])("div",o,[s.showWeather?(Object(a["r"])(),Object(a["e"])(w,{key:0,"show-summary":m._showSummary,animate:m._animate,"icon-size":s.iconSize,"refresh-seconds":s.weatherRefreshSeconds},null,8,["show-summary","animate","icon-size","refresh-seconds"])):Object(a["f"])("",!0)]),Object(a["h"])("div",c,[m._showSensors&&Object.keys(e.sensors).length?(Object(a["r"])(),Object(a["e"])("div",u,[Object(a["h"])("div",d,[null!=e.sensors.temperature?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-thermometer-half",value:e.sensors.temperature,unit:"°"},null,8,["value"])):Object(a["f"])("",!0)]),h,Object(a["h"])("div",l,[null!=e.sensors.humidity?(Object(a["r"])(),Object(a["e"])(j,{key:0,"icon-class":"fas fa-tint",value:e.sensors.humidity,unit:"%"},null,8,["value"])):Object(a["f"])("",!0)])])):Object(a["f"])("",!0)])])})),m=(s("a9e3"),s("3e54")),f=s("365a"),w=s("5b43"),j=(s("b0c0"),Object(a["J"])("data-v-1efb373e"));Object(a["u"])("data-v-1efb373e");var O={class:"sensor"},p={key:0,class:"label-container col-6"},v={class:"value-container col-6"};Object(a["s"])();var y=j((function(e,t,s,n,r,i){return Object(a["r"])(),Object(a["e"])("div",O,[s.iconClass||s.name?(Object(a["r"])(),Object(a["e"])("div",p,[s.iconClass?(Object(a["r"])(),Object(a["e"])("i",{key:0,class:s.iconClass},null,2)):s.name?(Object(a["r"])(),Object(a["e"])("span",{key:1,textContent:Object(a["C"])(s.name)},null,8,["textContent"])):Object(a["f"])("",!0)])):Object(a["f"])("",!0),Object(a["h"])("div",v,[Object(a["h"])("span",{class:"value",textContent:Object(a["C"])(i._value)},null,8,["textContent"])])])})),S=(s("99af"),s("b680"),{name:"Sensor",props:{iconClass:{type:String,required:!1},name:{type:String,required:!1},value:{required:!1},unit:{type:String,required:!1},decimals:{type:Number,required:!1,default:1},isBoolean:{type:Boolean,required:!1,default:!1}},computed:{_value:function(){if(null==this.value)return"N/A";if(this.isBoolean)return this.parseBoolean(this.value);var e=parseFloat(this.value);return null!=this.decimals&&(e=e.toFixed(this.decimals)),this.unit&&(e="".concat(e).concat(this.unit)),e}}});s("2e0b");S.render=y,S.__scopeId="data-v-1efb373e";var _=S,q={name:"DateTimeWeather",mixins:[m["a"]],components:{Sensor:_,DateTime:f["default"],Weather:w["default"]},props:{animate:{required:!1,default:!0},iconSize:{type:Number,required:!1,default:50},showDate:{required:!1,default:!0},showTime:{required:!1,default:!0},showWeather:{required:!1,default:!0},showSummary:{required:!1,default:!0},showSensors:{required:!1,default:!0},showSeconds:{required:!1,default:!0},sensorTemperatureAttr:{type:String,required:!1,default:"temperature"},sensorHumidityAttr:{type:String,required:!1,default:"humidity"},weatherRefreshSeconds:{type:Number,required:!1,default:900}},computed:{_showDate:function(){return this.parseBoolean(this.showDate)},_showTime:function(){return this.parseBoolean(this.showTime)},_showSeconds:function(){return this.parseBoolean(this.showSeconds)},_showWeather:function(){return this.parseBoolean(this.showWeather)},_showSummary:function(){return this.parseBoolean(this.showSummary)},_showSensors:function(){return this.parseBoolean(this.showSensors)},_animate:function(){return this.parseBoolean(this.animate)}},data:function(){return{sensors:{}}},methods:{onSensorData:function(e){this.sensorTemperatureAttr in e.data&&(this.sensors.temperature=e.data.temperature),this.sensorHumidityAttr in e.data&&(this.sensors.humidity=e.data.humidity)}},mounted:function(){this.subscribe(this.onSensorData,"platypush.message.event.sensor.SensorDataChangeEvent")}};s("cd6d");q.render=b,q.__scopeId="data-v-6bc0bd70";t["default"]=q},"5d41":function(e,t,s){},cd6d:function(e,t,s){"use strict";s("5d41")},e458:function(e,t,s){}}]);
//# sourceMappingURL=chunk-5710a9bc.47bb3f2d.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -23,6 +23,7 @@ export default {
timeout: null,
reconnectMsecs: 30000,
handlers: {},
handlerNameToEventTypes: {},
}
},
@ -60,7 +61,7 @@ export default {
}
if (event.args.type in this.handlers) {
handlers.push(...this.handlers[event.args.type])
handlers.push(...Object.values(this.handlers[event.args.type]))
}
for (let handler of handlers) {
@ -134,32 +135,40 @@ export default {
subscribe(msg) {
const handler = msg.handler
const events = msg.events.length ? msg.events : [null]
const handlerName = msg.handlerName
for (const event of events) {
if (!(event in this.handlers)) {
this.handlers[event] = []
this.handlers[event] = {}
}
this.handlers[event].push(handler)
if (!(handlerName in this.handlerNameToEventTypes)) {
this.handlerNameToEventTypes[handlerName] = events
}
this.handlers[event][handlerName] = handler
}
return () => {
this.unsubscribe(handlerName)
}
},
unsubscribe(msg) {
const handler = msg.handler
const events = msg.events.length ? msg.events : [null]
unsubscribe(handlerName) {
const events = this.handlerNameToEventTypes[handlerName]
if (!events)
return
for (const event of events) {
if (!(event in this.handlers))
if (!this.handlers[event]?.[handlerName])
continue
const idx = this.handlers[event].indexOf(handler)
if (idx < 0)
continue
this.handlers[event] = this.handlers[event].splice(idx, 1)[1]
if (!this.handlers[event].length)
delete this.handlers[event][handlerName]
if (!Object.keys(this.handlers[event]).length)
delete this.handlers[event]
}
delete this.handlerNameToEventTypes[handlerName]
},
},

View file

@ -30,8 +30,7 @@
<i class="icon far fa-image" />
<span class="view-title">&nbsp; Scenes</span>
</button>
<button :class="{selected: selectedView === 'animate'}" title="Animate"
@click="selectedView = 'animate'">
<button :class="{selected: selectedView === 'animate'}" title="Animate" @click="selectedView = 'animate'">
<i class="icon fas fa-video" />
<span class="view-title">&nbsp; Animate</span>
</button>

View file

@ -25,7 +25,7 @@ export default {
},
mounted() {
this.subscribe(this.onMessage, 'platypush.message.event.pushbullet.PushbulletEvent')
this.subscribe(this.onMessage, null, 'platypush.message.event.pushbullet.PushbulletEvent')
},
}
</script>

View file

@ -105,12 +105,12 @@ export default {
},
registerHandlers() {
this.subscribe(this.conversationStart, 'platypush.message.event.assistant.ConversationStartEvent')
this.subscribe(this.alertOn, 'platypush.message.event.assistant.AlertStartedEvent')
this.subscribe(this.alertOff, 'platypush.message.event.assistant.AlertEndEvent')
this.subscribe(this.speechRecognized, 'platypush.message.event.assistant.SpeechRecognizedEvent')
this.subscribe(this.response, 'platypush.message.event.assistant.ResponseEvent')
this.subscribe(this.conversationEnd,
this.subscribe(this.conversationStart, null, 'platypush.message.event.assistant.ConversationStartEvent')
this.subscribe(this.alertOn, null, 'platypush.message.event.assistant.AlertStartedEvent')
this.subscribe(this.alertOff, null, 'platypush.message.event.assistant.AlertEndEvent')
this.subscribe(this.speechRecognized, null, 'platypush.message.event.assistant.SpeechRecognizedEvent')
this.subscribe(this.response, null, 'platypush.message.event.assistant.ResponseEvent')
this.subscribe(this.conversationEnd, null,
'platypush.message.event.assistant.ConversationEndEvent',
'platypush.message.event.assistant.NoResponseEvent',
'platypush.message.event.assistant.ConversationTimeoutEvent')

View file

@ -6,7 +6,7 @@
</div>
<div class="panel" v-else>
<Group :group="groups[selectedGroup]" :lights="displayedLights" :scenes="scenesByGroup[selectedGroup]"
:color-converter="colorConverter" :animations="animationsByGroup[selectedGroup]" @close="closeGroup"
:color-converter="colorConverter" :animations="animationsByGroup[selectedGroup]" @close="selectedGroup = null"
@light-toggle="$emit('light-toggle', $event)" @group-toggle="$emit('group-toggle', $event)"
@set-light="$emit('set-light', $event)"
@set-group="$emit('set-group', {groupId: selectedGroup, value: $event})"
@ -30,7 +30,8 @@ export default {
name: "Light",
components: {Group, Groups},
mixins: [Utils, Panel],
emits: ['group-toggle', 'light-toggle', 'set-light', 'set-group', 'select-scene', 'start-animation', 'stop-animation'],
emits: ['group-toggle', 'light-toggle', 'set-light', 'set-group', 'select-scene', 'start-animation', 'stop-animation',
'refresh'],
props: {
lights: {
@ -168,14 +169,50 @@ export default {
})
},
closeGroup() {
this.selectedGroup = null
refresh() {
this.$emit('refresh')
},
onLightChange(event) {
if (event.plugin_name !== this.pluginName)
return
if (!this.lights[event.light_id]) {
this.refresh()
return
}
delete event.plugin_name
delete event.type
this.lights[event.light_id].state = {
...(this.lights[event.light_id]?.state || {}),
...event,
}
},
onAnimationChange(event) {
if (event.plugin_name !== this.pluginName)
return
this.refresh()
},
},
mounted() {
this.subscribe(this.onLightChange, 'on-light-change',
'platypush.message.event.light.LightStatusChangeEvent')
this.subscribe(this.onAnimationChange, 'on-animation-change',
'platypush.message.event.light.LightAnimationStartedEvent',
'platypush.message.event.light.LightAnimationStoppedEvent')
this.initSelectedGroup()
},
destroyed() {
this.unsubscribe('on-light-change')
this.unsubscribe('on-animation-change')
},
}
</script>

View file

@ -4,7 +4,7 @@
:animations="animations" :initial-group="initialGroup" :loading-groups="loadingGroups"
:color-converter="colorConverter" @group-toggle="toggleGroup"
@light-toggle="toggleLight" @set-light="setLight" @set-group="setGroup" @select-scene="setScene"
@start-animation="startAnimation" @stop-animation="stopAnimation" />
@start-animation="startAnimation" @stop-animation="stopAnimation" @refresh="refresh(true)"/>
</template>
<script>

View file

@ -161,7 +161,7 @@ export default {
},
mounted() {
this.subscribe(this.onSensorData, 'platypush.message.event.sensor.SensorDataChangeEvent');
this.subscribe(this.onSensorData, null, 'platypush.message.event.sensor.SensorDataChangeEvent');
},
}
</script>

View file

@ -289,16 +289,16 @@ export default {
setInterval(this.refresh, parseInt((this.refreshSeconds*1000).toFixed(0)))
}
this.subscribe(this.onNewPlayingTrack, 'platypush.message.event.music.NewPlayingTrackEvent')
this.subscribe(this.onMusicStop, 'platypush.message.event.music.MusicStopEvent')
this.subscribe(this.onMusicPlay, 'platypush.message.event.music.MusicPlayEvent')
this.subscribe(this.onMusicPause, 'platypush.message.event.music.MusicPauseEvent')
this.subscribe(this.onSeekChange, 'platypush.message.event.music.SeekChangeEvent')
this.subscribe(this.onVolumeChange, 'platypush.message.event.music.VolumeChangeEvent')
this.subscribe(this.onRepeatChange, 'platypush.message.event.music.PlaybackRepeatModeChangeEvent')
this.subscribe(this.onRandomChange, 'platypush.message.event.music.PlaybackRandomModeChangeEvent')
this.subscribe(this.onConsumeChange, 'platypush.message.event.music.PlaybackConsumeModeChangeEvent')
this.subscribe(this.onSingleChange, 'platypush.message.event.music.PlaybackSingleModeChangeEvent')
this.subscribe(this.onNewPlayingTrack, 'widget-music-on-new-track', 'platypush.message.event.music.NewPlayingTrackEvent')
this.subscribe(this.onMusicStop, 'widget-music-on-music-stop', 'platypush.message.event.music.MusicStopEvent')
this.subscribe(this.onMusicPlay, 'widget-music-on-music-play', 'platypush.message.event.music.MusicPlayEvent')
this.subscribe(this.onMusicPause, 'widget-music-on-music-pause', 'platypush.message.event.music.MusicPauseEvent')
this.subscribe(this.onSeekChange, 'widget-music-on-music-seek', 'platypush.message.event.music.SeekChangeEvent')
this.subscribe(this.onVolumeChange, 'widget-music-on-volume-change', 'platypush.message.event.music.VolumeChangeEvent')
this.subscribe(this.onRepeatChange, 'widget-music-on-repeat-change', 'platypush.message.event.music.PlaybackRepeatModeChangeEvent')
this.subscribe(this.onRandomChange, 'widget-music-on-random-change', 'platypush.message.event.music.PlaybackRandomModeChangeEvent')
this.subscribe(this.onConsumeChange, 'widget-music-on-consume-change', 'platypush.message.event.music.PlaybackConsumeModeChangeEvent')
this.subscribe(this.onSingleChange, 'widget-music-on-single-change', 'platypush.message.event.music.PlaybackSingleModeChangeEvent')
},
}
</script>

View file

@ -116,7 +116,7 @@ export default {
mounted: function() {
this.refresh()
this.subscribe(this.onWeatherChange, 'platypush.message.event.weather.NewWeatherConditionEvent')
this.subscribe(this.onWeatherChange, null, 'platypush.message.event.weather.NewWeatherConditionEvent')
setInterval(this.refresh, parseInt((this.refreshSeconds*1000).toFixed(0)))
},
}

View file

@ -10,11 +10,12 @@ export default {
},
methods: {
subscribe(handler, ...events) {
subscribe(handler, handlerName, ...events) {
const subFunc = () => {
bus.emit('subscribe', {
events: events,
handler: handler,
handlerName: handlerName || this.generateId(),
})
}
@ -31,6 +32,14 @@ export default {
}
})
},
unsubscribe(handlerName) {
bus.emit('unsubscribe', handlerName)
},
generateId() {
return btoa([...Array(16).keys()].forEach(() => String.fromCharCode(Math.round(Math.random() * 255))))
},
}
}
</script>

View file

@ -36,8 +36,8 @@ class LightHueBackend(Backend):
super().__init__(*args, **kwargs)
self.poll_seconds = poll_seconds
def _get_lights(self):
@staticmethod
def _get_lights():
plugin = get_plugin('light.hue')
if not plugin:
plugin = get_plugin('light.hue', reload=True)
@ -67,8 +67,11 @@ class LightHueBackend(Backend):
event_args['hue'] = state.get('hue')
if 'ct' in state and state.get('ct') != prev_state.get('ct'):
event_args['ct'] = state.get('ct')
if 'xy' in state and state.get('xy') != prev_state.get('xy'):
event_args['xy'] = state.get('xy')
if event_args:
event_args['plugin_name'] = 'light.hue'
event_args['light_id'] = light_id
event_args['light_name'] = light.get('name')
self.bus.post(LightStatusChangeEvent(**event_args))
@ -93,4 +96,5 @@ class LightHueBackend(Backend):
self.logger.exception(e)
time.sleep(self.poll_seconds)
# vim:sw=4:ts=4:et:

View file

@ -1,13 +1,25 @@
from typing import Optional
from platypush.message.event import Event
class LightStatusChangeEvent(Event):
class LightEvent(Event):
"""
Base class for light plugins events.
"""
def __init__(self, *args, plugin_name: Optional[str] = None, **kwargs):
"""
:param plugin_name: Name of the :class:`platypush.plugins.light.LightPlugin` instance that triggered the event.
"""
super().__init__(*args, plugin_name=plugin_name, **kwargs)
class LightStatusChangeEvent(LightEvent):
"""
Event triggered when the state of a lightbulb changes
"""
def __init__(self, light_id=None, light_name=None, on=None, bri=None,
sat=None, hue=None, ct=None, *args, **kwargs):
sat=None, hue=None, ct=None, xy=None, *args, **kwargs):
"""
:param light_id: Light ID that triggered the event
:type light_id: int
@ -29,6 +41,9 @@ class LightStatusChangeEvent(Event):
:param ct: Set if the color temperature state of the bulb changed
:type ct: int
:param xy: Set if the color of the bulb (expressed in XY coordinates) has changed
:type xy: list
"""
attrs = {}
@ -47,9 +62,26 @@ class LightStatusChangeEvent(Event):
attrs['hue'] = hue
if ct is not None:
attrs['ct'] = ct
if xy is not None:
attrs['xy'] = xy
super().__init__(*args, **attrs, **kwargs)
# vim:sw=4:ts=4:et:
class LightAnimationStartedEvent(LightEvent):
"""
Event triggered when a light animation is started.
"""
def __init__(self, *args, animation, lights: Optional[list] = None, groups: Optional[list] = None, **kwargs):
super().__init__(*args, animation=animation, lights=lights, groups=groups, **kwargs)
class LightAnimationStoppedEvent(LightEvent):
"""
Event triggered when a light animation is stopped.
"""
def __init__(self, *args, animation=None, lights: Optional[list] = None, groups: Optional[list] = None, **kwargs):
super().__init__(*args, animation=animation, lights=lights, groups=groups, **kwargs)
# vim:sw=4:ts=4:et:

View file

@ -5,6 +5,8 @@ import time
from enum import Enum
from threading import Thread, Event
from platypush.context import get_bus
from platypush.message.event.light import LightAnimationStartedEvent, LightAnimationStoppedEvent
from platypush.plugins import action
from platypush.plugins.light import LightPlugin
from platypush.utils import set_thread_name
@ -17,6 +19,12 @@ class LightHuePlugin(LightPlugin):
Requires:
* **phue** (``pip install phue``)
Triggers:
- :class:`platypush.message.event.light.LightAnimationStartedEvent` when an animation is started.
- :class:`platypush.message.event.light.LightAnimationStoppedEvent` when an animation is stopped.
"""
MAX_BRI = 255
@ -851,7 +859,7 @@ class LightHuePlugin(LightPlugin):
def _animate_thread(lights):
set_thread_name('HueAnimate')
self.logger.info('Starting {} animation'.format(animation, (lights or groups)))
get_bus().post(LightAnimationStartedEvent(lights=lights, groups=groups, animation=animation))
lights = _initialize_light_attrs(lights)
animation_start_time = time.time()
@ -882,7 +890,7 @@ class LightHuePlugin(LightPlugin):
lights = _next_light_attrs(lights)
self.logger.info('Stopping animation')
get_bus().post(LightAnimationStoppedEvent(lights=lights, groups=groups, animation=animation))
self.animation_thread = None
self.animation_thread = Thread(target=_animate_thread,