Support for subscribe-once/unsubscribe frontend events mechanisms
This commit is contained in:
parent
0db997c6a0
commit
5d4f4b0378
46 changed files with 173 additions and 75 deletions
2
platypush/backend/http/dist/index.html
vendored
2
platypush/backend/http/dist/index.html
vendored
|
@ -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
1
platypush/backend/http/dist/static/css/chunk-35b45d59.bea59a51.css
vendored
Normal file
1
platypush/backend/http/dist/static/css/chunk-35b45d59.bea59a51.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/css/chunk-53360c78.2281ab32.css
vendored
Normal file
1
platypush/backend/http/dist/static/css/chunk-53360c78.2281ab32.css
vendored
Normal file
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
2
platypush/backend/http/dist/static/js/app.41ee3441.js
vendored
Normal file
2
platypush/backend/http/dist/static/js/app.41ee3441.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/app.41ee3441.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/app.41ee3441.js.map
vendored
Normal file
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
2
platypush/backend/http/dist/static/js/chunk-2d2091df.8d32d3ba.js
vendored
Normal file
2
platypush/backend/http/dist/static/js/chunk-2d2091df.8d32d3ba.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/chunk-2d2091df.8d32d3ba.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-2d2091df.8d32d3ba.js.map
vendored
Normal file
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
2
platypush/backend/http/dist/static/js/chunk-35b45d59.d541d43f.js
vendored
Normal file
2
platypush/backend/http/dist/static/js/chunk-35b45d59.d541d43f.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/chunk-35b45d59.d541d43f.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-35b45d59.d541d43f.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
platypush/backend/http/dist/static/js/chunk-45939517.38162e50.js
vendored
Normal file
2
platypush/backend/http/dist/static/js/chunk-45939517.38162e50.js
vendored
Normal 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
|
1
platypush/backend/http/dist/static/js/chunk-45939517.38162e50.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-45939517.38162e50.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/chunk-53360c78.54e2e626.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-53360c78.54e2e626.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -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
2
platypush/backend/http/dist/static/js/chunk-6fa461b6.d6fffa0d.js
vendored
Normal file
2
platypush/backend/http/dist/static/js/chunk-6fa461b6.d6fffa0d.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/chunk-6fa461b6.d6fffa0d.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-6fa461b6.d6fffa0d.js.map
vendored
Normal file
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
1
platypush/backend/http/dist/static/js/chunk-vendors.1eac7b43.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-vendors.1eac7b43.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -23,6 +23,7 @@ export default {
|
||||||
timeout: null,
|
timeout: null,
|
||||||
reconnectMsecs: 30000,
|
reconnectMsecs: 30000,
|
||||||
handlers: {},
|
handlers: {},
|
||||||
|
handlerNameToEventTypes: {},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.args.type in this.handlers) {
|
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) {
|
for (let handler of handlers) {
|
||||||
|
@ -134,32 +135,40 @@ export default {
|
||||||
subscribe(msg) {
|
subscribe(msg) {
|
||||||
const handler = msg.handler
|
const handler = msg.handler
|
||||||
const events = msg.events.length ? msg.events : [null]
|
const events = msg.events.length ? msg.events : [null]
|
||||||
|
const handlerName = msg.handlerName
|
||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
if (!(event in this.handlers)) {
|
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) {
|
unsubscribe(handlerName) {
|
||||||
const handler = msg.handler
|
const events = this.handlerNameToEventTypes[handlerName]
|
||||||
const events = msg.events.length ? msg.events : [null]
|
if (!events)
|
||||||
|
return
|
||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
if (!(event in this.handlers))
|
if (!this.handlers[event]?.[handlerName])
|
||||||
continue
|
continue
|
||||||
|
|
||||||
const idx = this.handlers[event].indexOf(handler)
|
delete this.handlers[event][handlerName]
|
||||||
if (idx < 0)
|
if (!Object.keys(this.handlers[event]).length)
|
||||||
continue
|
|
||||||
|
|
||||||
this.handlers[event] = this.handlers[event].splice(idx, 1)[1]
|
|
||||||
if (!this.handlers[event].length)
|
|
||||||
delete this.handlers[event]
|
delete this.handlers[event]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete this.handlerNameToEventTypes[handlerName]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
<i class="icon far fa-image" />
|
<i class="icon far fa-image" />
|
||||||
<span class="view-title"> Scenes</span>
|
<span class="view-title"> Scenes</span>
|
||||||
</button>
|
</button>
|
||||||
<button :class="{selected: selectedView === 'animate'}" title="Animate"
|
<button :class="{selected: selectedView === 'animate'}" title="Animate" @click="selectedView = 'animate'">
|
||||||
@click="selectedView = 'animate'">
|
|
||||||
<i class="icon fas fa-video" />
|
<i class="icon fas fa-video" />
|
||||||
<span class="view-title"> Animate</span>
|
<span class="view-title"> Animate</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.subscribe(this.onMessage, 'platypush.message.event.pushbullet.PushbulletEvent')
|
this.subscribe(this.onMessage, null, 'platypush.message.event.pushbullet.PushbulletEvent')
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -105,12 +105,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
registerHandlers() {
|
registerHandlers() {
|
||||||
this.subscribe(this.conversationStart, 'platypush.message.event.assistant.ConversationStartEvent')
|
this.subscribe(this.conversationStart, null, 'platypush.message.event.assistant.ConversationStartEvent')
|
||||||
this.subscribe(this.alertOn, 'platypush.message.event.assistant.AlertStartedEvent')
|
this.subscribe(this.alertOn, null, 'platypush.message.event.assistant.AlertStartedEvent')
|
||||||
this.subscribe(this.alertOff, 'platypush.message.event.assistant.AlertEndEvent')
|
this.subscribe(this.alertOff, null, 'platypush.message.event.assistant.AlertEndEvent')
|
||||||
this.subscribe(this.speechRecognized, 'platypush.message.event.assistant.SpeechRecognizedEvent')
|
this.subscribe(this.speechRecognized, null, 'platypush.message.event.assistant.SpeechRecognizedEvent')
|
||||||
this.subscribe(this.response, 'platypush.message.event.assistant.ResponseEvent')
|
this.subscribe(this.response, null, 'platypush.message.event.assistant.ResponseEvent')
|
||||||
this.subscribe(this.conversationEnd,
|
this.subscribe(this.conversationEnd, null,
|
||||||
'platypush.message.event.assistant.ConversationEndEvent',
|
'platypush.message.event.assistant.ConversationEndEvent',
|
||||||
'platypush.message.event.assistant.NoResponseEvent',
|
'platypush.message.event.assistant.NoResponseEvent',
|
||||||
'platypush.message.event.assistant.ConversationTimeoutEvent')
|
'platypush.message.event.assistant.ConversationTimeoutEvent')
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="panel" v-else>
|
<div class="panel" v-else>
|
||||||
<Group :group="groups[selectedGroup]" :lights="displayedLights" :scenes="scenesByGroup[selectedGroup]"
|
<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)"
|
@light-toggle="$emit('light-toggle', $event)" @group-toggle="$emit('group-toggle', $event)"
|
||||||
@set-light="$emit('set-light', $event)"
|
@set-light="$emit('set-light', $event)"
|
||||||
@set-group="$emit('set-group', {groupId: selectedGroup, value: $event})"
|
@set-group="$emit('set-group', {groupId: selectedGroup, value: $event})"
|
||||||
|
@ -30,7 +30,8 @@ export default {
|
||||||
name: "Light",
|
name: "Light",
|
||||||
components: {Group, Groups},
|
components: {Group, Groups},
|
||||||
mixins: [Utils, Panel],
|
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: {
|
props: {
|
||||||
lights: {
|
lights: {
|
||||||
|
@ -168,14 +169,50 @@ export default {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
closeGroup() {
|
refresh() {
|
||||||
this.selectedGroup = null
|
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() {
|
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()
|
this.initSelectedGroup()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
destroyed() {
|
||||||
|
this.unsubscribe('on-light-change')
|
||||||
|
this.unsubscribe('on-animation-change')
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
:animations="animations" :initial-group="initialGroup" :loading-groups="loadingGroups"
|
:animations="animations" :initial-group="initialGroup" :loading-groups="loadingGroups"
|
||||||
:color-converter="colorConverter" @group-toggle="toggleGroup"
|
:color-converter="colorConverter" @group-toggle="toggleGroup"
|
||||||
@light-toggle="toggleLight" @set-light="setLight" @set-group="setGroup" @select-scene="setScene"
|
@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>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -161,7 +161,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.subscribe(this.onSensorData, 'platypush.message.event.sensor.SensorDataChangeEvent');
|
this.subscribe(this.onSensorData, null, 'platypush.message.event.sensor.SensorDataChangeEvent');
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -289,16 +289,16 @@ export default {
|
||||||
setInterval(this.refresh, parseInt((this.refreshSeconds*1000).toFixed(0)))
|
setInterval(this.refresh, parseInt((this.refreshSeconds*1000).toFixed(0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.subscribe(this.onNewPlayingTrack, 'platypush.message.event.music.NewPlayingTrackEvent')
|
this.subscribe(this.onNewPlayingTrack, 'widget-music-on-new-track', 'platypush.message.event.music.NewPlayingTrackEvent')
|
||||||
this.subscribe(this.onMusicStop, 'platypush.message.event.music.MusicStopEvent')
|
this.subscribe(this.onMusicStop, 'widget-music-on-music-stop', 'platypush.message.event.music.MusicStopEvent')
|
||||||
this.subscribe(this.onMusicPlay, 'platypush.message.event.music.MusicPlayEvent')
|
this.subscribe(this.onMusicPlay, 'widget-music-on-music-play', 'platypush.message.event.music.MusicPlayEvent')
|
||||||
this.subscribe(this.onMusicPause, 'platypush.message.event.music.MusicPauseEvent')
|
this.subscribe(this.onMusicPause, 'widget-music-on-music-pause', 'platypush.message.event.music.MusicPauseEvent')
|
||||||
this.subscribe(this.onSeekChange, 'platypush.message.event.music.SeekChangeEvent')
|
this.subscribe(this.onSeekChange, 'widget-music-on-music-seek', 'platypush.message.event.music.SeekChangeEvent')
|
||||||
this.subscribe(this.onVolumeChange, 'platypush.message.event.music.VolumeChangeEvent')
|
this.subscribe(this.onVolumeChange, 'widget-music-on-volume-change', 'platypush.message.event.music.VolumeChangeEvent')
|
||||||
this.subscribe(this.onRepeatChange, 'platypush.message.event.music.PlaybackRepeatModeChangeEvent')
|
this.subscribe(this.onRepeatChange, 'widget-music-on-repeat-change', 'platypush.message.event.music.PlaybackRepeatModeChangeEvent')
|
||||||
this.subscribe(this.onRandomChange, 'platypush.message.event.music.PlaybackRandomModeChangeEvent')
|
this.subscribe(this.onRandomChange, 'widget-music-on-random-change', 'platypush.message.event.music.PlaybackRandomModeChangeEvent')
|
||||||
this.subscribe(this.onConsumeChange, 'platypush.message.event.music.PlaybackConsumeModeChangeEvent')
|
this.subscribe(this.onConsumeChange, 'widget-music-on-consume-change', 'platypush.message.event.music.PlaybackConsumeModeChangeEvent')
|
||||||
this.subscribe(this.onSingleChange, 'platypush.message.event.music.PlaybackSingleModeChangeEvent')
|
this.subscribe(this.onSingleChange, 'widget-music-on-single-change', 'platypush.message.event.music.PlaybackSingleModeChangeEvent')
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -116,7 +116,7 @@ export default {
|
||||||
|
|
||||||
mounted: function() {
|
mounted: function() {
|
||||||
this.refresh()
|
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)))
|
setInterval(this.refresh, parseInt((this.refreshSeconds*1000).toFixed(0)))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
subscribe(handler, ...events) {
|
subscribe(handler, handlerName, ...events) {
|
||||||
const subFunc = () => {
|
const subFunc = () => {
|
||||||
bus.emit('subscribe', {
|
bus.emit('subscribe', {
|
||||||
events: events,
|
events: events,
|
||||||
handler: handler,
|
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>
|
</script>
|
||||||
|
|
|
@ -36,8 +36,8 @@ class LightHueBackend(Backend):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.poll_seconds = poll_seconds
|
self.poll_seconds = poll_seconds
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def _get_lights(self):
|
def _get_lights():
|
||||||
plugin = get_plugin('light.hue')
|
plugin = get_plugin('light.hue')
|
||||||
if not plugin:
|
if not plugin:
|
||||||
plugin = get_plugin('light.hue', reload=True)
|
plugin = get_plugin('light.hue', reload=True)
|
||||||
|
@ -67,8 +67,11 @@ class LightHueBackend(Backend):
|
||||||
event_args['hue'] = state.get('hue')
|
event_args['hue'] = state.get('hue')
|
||||||
if 'ct' in state and state.get('ct') != prev_state.get('ct'):
|
if 'ct' in state and state.get('ct') != prev_state.get('ct'):
|
||||||
event_args['ct'] = 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:
|
if event_args:
|
||||||
|
event_args['plugin_name'] = 'light.hue'
|
||||||
event_args['light_id'] = light_id
|
event_args['light_id'] = light_id
|
||||||
event_args['light_name'] = light.get('name')
|
event_args['light_name'] = light.get('name')
|
||||||
self.bus.post(LightStatusChangeEvent(**event_args))
|
self.bus.post(LightStatusChangeEvent(**event_args))
|
||||||
|
@ -93,4 +96,5 @@ class LightHueBackend(Backend):
|
||||||
self.logger.exception(e)
|
self.logger.exception(e)
|
||||||
time.sleep(self.poll_seconds)
|
time.sleep(self.poll_seconds)
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from platypush.message.event import Event
|
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
|
Event triggered when the state of a lightbulb changes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, light_id=None, light_name=None, on=None, bri=None,
|
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
|
:param light_id: Light ID that triggered the event
|
||||||
:type light_id: int
|
:type light_id: int
|
||||||
|
@ -29,6 +41,9 @@ class LightStatusChangeEvent(Event):
|
||||||
|
|
||||||
:param ct: Set if the color temperature state of the bulb changed
|
:param ct: Set if the color temperature state of the bulb changed
|
||||||
:type ct: int
|
:type ct: int
|
||||||
|
|
||||||
|
:param xy: Set if the color of the bulb (expressed in XY coordinates) has changed
|
||||||
|
:type xy: list
|
||||||
"""
|
"""
|
||||||
|
|
||||||
attrs = {}
|
attrs = {}
|
||||||
|
@ -47,9 +62,26 @@ class LightStatusChangeEvent(Event):
|
||||||
attrs['hue'] = hue
|
attrs['hue'] = hue
|
||||||
if ct is not None:
|
if ct is not None:
|
||||||
attrs['ct'] = ct
|
attrs['ct'] = ct
|
||||||
|
if xy is not None:
|
||||||
|
attrs['xy'] = xy
|
||||||
|
|
||||||
super().__init__(*args, **attrs, **kwargs)
|
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:
|
||||||
|
|
|
@ -5,6 +5,8 @@ import time
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from threading import Thread, Event
|
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 import action
|
||||||
from platypush.plugins.light import LightPlugin
|
from platypush.plugins.light import LightPlugin
|
||||||
from platypush.utils import set_thread_name
|
from platypush.utils import set_thread_name
|
||||||
|
@ -17,6 +19,12 @@ class LightHuePlugin(LightPlugin):
|
||||||
Requires:
|
Requires:
|
||||||
|
|
||||||
* **phue** (``pip install phue``)
|
* **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
|
MAX_BRI = 255
|
||||||
|
@ -851,7 +859,7 @@ class LightHuePlugin(LightPlugin):
|
||||||
|
|
||||||
def _animate_thread(lights):
|
def _animate_thread(lights):
|
||||||
set_thread_name('HueAnimate')
|
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)
|
lights = _initialize_light_attrs(lights)
|
||||||
animation_start_time = time.time()
|
animation_start_time = time.time()
|
||||||
|
@ -882,7 +890,7 @@ class LightHuePlugin(LightPlugin):
|
||||||
|
|
||||||
lights = _next_light_attrs(lights)
|
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 = None
|
||||||
|
|
||||||
self.animation_thread = Thread(target=_animate_thread,
|
self.animation_thread = Thread(target=_animate_thread,
|
||||||
|
|
Loading…
Reference in a new issue