Adding the strobe effect, better splitting into components
This commit is contained in:
parent
14f6802da2
commit
211b8965c5
9 changed files with 1404 additions and 147 deletions
|
|
@ -7,7 +7,17 @@ export default Em.Component.extend({
|
||||||
|
|
||||||
lightsData: null,
|
lightsData: null,
|
||||||
|
|
||||||
lightsDataIntervalHandle: null,
|
numLights: function(){
|
||||||
|
var lightsData = this.get('lightsData'), numLights = 0;
|
||||||
|
|
||||||
|
for (let key in this.get('lightsData')) {
|
||||||
|
if(lightsData.hasOwnProperty(key)){
|
||||||
|
numLights++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return numLights;
|
||||||
|
}.property('lightsData'),
|
||||||
|
|
||||||
lightsApiURL: function(){
|
lightsApiURL: function(){
|
||||||
return 'http://' + this.get('bridgeIp') + '/api/' + this.get('bridgeUsername') + '/lights';
|
return 'http://' + this.get('bridgeIp') + '/api/' + this.get('bridgeUsername') + '/lights';
|
||||||
|
|
@ -17,144 +27,21 @@ export default Em.Component.extend({
|
||||||
this.set('lightsDataIntervalHandle', setInterval(this.updateLightData.bind(this), 1000));
|
this.set('lightsDataIntervalHandle', setInterval(this.updateLightData.bind(this), 1000));
|
||||||
},
|
},
|
||||||
|
|
||||||
// determines whether the lights are on/off for the lights switch
|
|
||||||
lightsOn: function(){
|
|
||||||
var lightsData = this.get('lightsData');
|
|
||||||
|
|
||||||
for (var key in lightsData) {
|
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
|
||||||
if(lightsData[key].state.on){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}.property('lightsData'),
|
|
||||||
|
|
||||||
// determines the average brightness of the hue system for the brightness slider
|
|
||||||
lightsBrightness: function(){
|
|
||||||
var lightsData = this.get('lightsData'), lightsBrightness = 0;
|
|
||||||
|
|
||||||
for (var key in lightsData) {
|
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
|
||||||
lightsBrightness += lightsData[key].state.bri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lightsBrightness/this.get('lightsList').length;
|
|
||||||
}.property('lightsData', 'lightsList'),
|
|
||||||
|
|
||||||
// list of all the lights in the hue system
|
|
||||||
lightsList: function(){
|
|
||||||
var lightsData = this.get('lightsData'), lightsList = [];
|
|
||||||
for (var key in lightsData) {
|
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
|
||||||
switch(lightsData[key].modelid){
|
|
||||||
case 'LCT001':
|
|
||||||
lightsList.push('a19');
|
|
||||||
break;
|
|
||||||
case 'LCT002':
|
|
||||||
lightsList.push('br30');
|
|
||||||
break;
|
|
||||||
case 'LCT003':
|
|
||||||
lightsList.push('gu10');
|
|
||||||
break;
|
|
||||||
case 'LST001':
|
|
||||||
lightsList.push('lightstrip');
|
|
||||||
break;
|
|
||||||
case 'LLC010':
|
|
||||||
lightsList.push('lc_iris');
|
|
||||||
break;
|
|
||||||
case 'LLC011':
|
|
||||||
lightsList.push('lc_bloom');
|
|
||||||
break;
|
|
||||||
case 'LLC012':
|
|
||||||
lightsList.push('lc_bloom');
|
|
||||||
break;
|
|
||||||
case 'LLC006':
|
|
||||||
lightsList.push('lc_iris');
|
|
||||||
break;
|
|
||||||
case 'LLC007':
|
|
||||||
lightsList.push('lc_aura');
|
|
||||||
break;
|
|
||||||
case 'LLC013':
|
|
||||||
lightsList.push('storylight');
|
|
||||||
break;
|
|
||||||
case 'LWB004':
|
|
||||||
lightsList.push('a19');
|
|
||||||
break;
|
|
||||||
case 'LLC020':
|
|
||||||
lightsList.push('huego');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
lightsList.push('a19');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lightsList;
|
|
||||||
}.property('lightsData'),
|
|
||||||
|
|
||||||
brightnessControlDisabled: function(){
|
|
||||||
return !this.get('lightsOn');
|
|
||||||
}.property('lightsOn'),
|
|
||||||
|
|
||||||
onLightsOnChange: function(){
|
|
||||||
var lightsData = this.get('lightsData'), lightsOnSystem = false, lightsOn = this.get('lightsOn');
|
|
||||||
|
|
||||||
for (let key in lightsData) {
|
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
|
||||||
if(lightsData[key].state.on){
|
|
||||||
lightsOnSystem = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
|
||||||
if(lightsOn !== lightsOnSystem){
|
|
||||||
for (let key in lightsData) {
|
|
||||||
Em.$.ajax(this.get('lightsApiURL') + '/' + key + '/state', {
|
|
||||||
data: JSON.stringify({"on": lightsOn}),
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'PUT'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.observes('lightsOn'),
|
|
||||||
|
|
||||||
onBrightnessChange: function(){
|
|
||||||
var lightsData = this.get('lightsData'), lightsBrightnessSystem = false, lightsBrightness = this.get('lightsBrightness');
|
|
||||||
|
|
||||||
for (let key in lightsData) {
|
|
||||||
if (lightsData.hasOwnProperty(key)) {
|
|
||||||
lightsBrightnessSystem += lightsData[key].state.bri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lightsBrightnessSystem /= this.get('lightsList').length;
|
|
||||||
|
|
||||||
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
|
||||||
if(lightsBrightness !== lightsBrightnessSystem){
|
|
||||||
for (let key in lightsData) {
|
|
||||||
Em.$.ajax(this.get('lightsApiURL') + '/' + key + '/state', {
|
|
||||||
data: JSON.stringify({"bri": lightsBrightness}),
|
|
||||||
contentType: 'application/json',
|
|
||||||
type: 'PUT'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.observes('lightsBrightness'),
|
|
||||||
|
|
||||||
lightsOnTxt: function(){
|
|
||||||
return this.get('lightsOn') ? 'On' : 'Off';
|
|
||||||
}.property('lightsOn'),
|
|
||||||
|
|
||||||
updateLightData: function(){
|
updateLightData: function(){
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
Em.$.get(this.get('lightsApiURL'), function (result, status) {
|
Em.$.get(this.get('lightsApiURL'), function (result, status) {
|
||||||
if (status === 'success') {
|
if (status === 'success' && JSON.stringify(self.get('lightsData')) !== JSON.stringify(result) ) {
|
||||||
self.set('lightsData', result);
|
self.set('lightsData', result);
|
||||||
|
} else if(status !== 'success' ) {
|
||||||
|
// something went terribly wrong ( user got unauthenticated? ) and we'll need to start all over
|
||||||
|
clearInterval(self.get('lightsDataIntervalHandle'));
|
||||||
|
this.setProperties({
|
||||||
|
bridgeIp: null,
|
||||||
|
bridgeUsername: null
|
||||||
|
});
|
||||||
|
|
||||||
|
console.error(status + ': ' + result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
141
app/components/controls/lights-control.js
Normal file
141
app/components/controls/lights-control.js
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
import Em from 'ember';
|
||||||
|
|
||||||
|
export default Em.Component.extend({
|
||||||
|
|
||||||
|
lightsDataIntervalHandle: null,
|
||||||
|
|
||||||
|
lightsApiURL: null,
|
||||||
|
|
||||||
|
lightsData: null,
|
||||||
|
|
||||||
|
// determines whether the lights are on/off for the lights switch
|
||||||
|
lightsOn: function(){
|
||||||
|
var lightsData = this.get('lightsData');
|
||||||
|
|
||||||
|
for (var key in lightsData) {
|
||||||
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
if(lightsData[key].state.on){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}.property('lightsData'),
|
||||||
|
|
||||||
|
// determines the average brightness of the hue system for the brightness slider
|
||||||
|
lightsBrightness: function(){
|
||||||
|
var lightsData = this.get('lightsData'), lightsBrightness = 0;
|
||||||
|
|
||||||
|
for (var key in lightsData) {
|
||||||
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
lightsBrightness += lightsData[key].state.bri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lightsBrightness/this.get('lightsList').length;
|
||||||
|
}.property('lightsData', 'lightsList'),
|
||||||
|
|
||||||
|
// list of all the lights in the hue system
|
||||||
|
lightsList: function(){
|
||||||
|
var lightsData = this.get('lightsData'), lightsList = [];
|
||||||
|
for (var key in lightsData) {
|
||||||
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
switch(lightsData[key].modelid){
|
||||||
|
case 'LCT001':
|
||||||
|
lightsList.push('a19');
|
||||||
|
break;
|
||||||
|
case 'LCT002':
|
||||||
|
lightsList.push('br30');
|
||||||
|
break;
|
||||||
|
case 'LCT003':
|
||||||
|
lightsList.push('gu10');
|
||||||
|
break;
|
||||||
|
case 'LST001':
|
||||||
|
lightsList.push('lightstrip');
|
||||||
|
break;
|
||||||
|
case 'LLC010':
|
||||||
|
lightsList.push('lc_iris');
|
||||||
|
break;
|
||||||
|
case 'LLC011':
|
||||||
|
lightsList.push('lc_bloom');
|
||||||
|
break;
|
||||||
|
case 'LLC012':
|
||||||
|
lightsList.push('lc_bloom');
|
||||||
|
break;
|
||||||
|
case 'LLC006':
|
||||||
|
lightsList.push('lc_iris');
|
||||||
|
break;
|
||||||
|
case 'LLC007':
|
||||||
|
lightsList.push('lc_aura');
|
||||||
|
break;
|
||||||
|
case 'LLC013':
|
||||||
|
lightsList.push('storylight');
|
||||||
|
break;
|
||||||
|
case 'LWB004':
|
||||||
|
lightsList.push('a19');
|
||||||
|
break;
|
||||||
|
case 'LLC020':
|
||||||
|
lightsList.push('huego');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lightsList.push('a19');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return lightsList;
|
||||||
|
}.property('lightsData'),
|
||||||
|
|
||||||
|
brightnessControlDisabled: Em.computed.not('lightsOn'),
|
||||||
|
|
||||||
|
onLightsOnChange: function(){
|
||||||
|
var lightsData = this.get('lightsData'), lightsOnSystem = false, lightsOn = this.get('lightsOn');
|
||||||
|
|
||||||
|
for (let key in lightsData) {
|
||||||
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
if(lightsData[key].state.on){
|
||||||
|
lightsOnSystem = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
|
if(lightsOn !== lightsOnSystem){
|
||||||
|
for (let key in lightsData) {
|
||||||
|
Em.$.ajax(this.get('lightsApiURL') + '/' + key + '/state', {
|
||||||
|
data: JSON.stringify({"on": lightsOn}),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.observes('lightsOn'),
|
||||||
|
|
||||||
|
onBrightnessChange: function(){
|
||||||
|
var lightsData = this.get('lightsData'), lightsBrightnessSystem = false, lightsBrightness = this.get('lightsBrightness');
|
||||||
|
|
||||||
|
for (let key in lightsData) {
|
||||||
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
lightsBrightnessSystem += lightsData[key].state.bri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lightsBrightnessSystem /= this.get('lightsList').length;
|
||||||
|
|
||||||
|
// if the internal lights state is different than the one from lightsData ( user manually toggled the switch ), send the request to change the bulbs state
|
||||||
|
if(lightsBrightness !== lightsBrightnessSystem){
|
||||||
|
for (let key in lightsData) {
|
||||||
|
Em.$.ajax(this.get('lightsApiURL') + '/' + key + '/state', {
|
||||||
|
data: JSON.stringify({"bri": lightsBrightness}),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.observes('lightsBrightness'),
|
||||||
|
|
||||||
|
lightsOnTxt: function(){
|
||||||
|
return this.get('lightsOn') ? 'On' : 'Off';
|
||||||
|
}.property('lightsOn')
|
||||||
|
});
|
||||||
82
app/components/controls/party-control.js
Normal file
82
app/components/controls/party-control.js
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
import Em from 'ember';
|
||||||
|
|
||||||
|
export default Em.Component.extend({
|
||||||
|
|
||||||
|
lightsApiURL: null,
|
||||||
|
|
||||||
|
strobeOn: false,
|
||||||
|
|
||||||
|
numLights: 0,
|
||||||
|
lightsData: null,
|
||||||
|
|
||||||
|
strobeOnInervalHandle: null,
|
||||||
|
strobeSat: 0,
|
||||||
|
preStrobeOnLightsDataCache: null,
|
||||||
|
lastStrobeLight: 0,
|
||||||
|
|
||||||
|
onStrobeOnChange: function () {
|
||||||
|
var lightsData = this.get('lightsData'), self = this;
|
||||||
|
|
||||||
|
if (this.get('strobeOn')) {
|
||||||
|
this.set('preStrobeOnLightsDataCache', lightsData);
|
||||||
|
var stobeInitRequestData = {'sat': this.get('strobeSat'), 'bri': 254, 'transitiontime': 0};
|
||||||
|
|
||||||
|
for (let key in lightsData) {
|
||||||
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
if (lightsData[key].state.on) {
|
||||||
|
stobeInitRequestData.on = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Em.$.ajax(this.get('lightsApiURL') + '/' + key + '/state', {
|
||||||
|
data: JSON.stringify(stobeInitRequestData),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set('strobeOnInervalHandle', setInterval(this.strobeStep.bind(this), 200));
|
||||||
|
} else { // revert the light system to pre-strobe
|
||||||
|
var preStrobeOnLightsDataCache = this.get('preStrobeOnLightsDataCache');
|
||||||
|
|
||||||
|
for (let key in lightsData) {
|
||||||
|
if (lightsData.hasOwnProperty(key)) {
|
||||||
|
setTimeout(function () {
|
||||||
|
Em.$.ajax(self.get('lightsApiURL') + '/' + key + '/state', {
|
||||||
|
data: JSON.stringify({
|
||||||
|
'on': preStrobeOnLightsDataCache[key].state.on,
|
||||||
|
'sat': preStrobeOnLightsDataCache[key].state.sat,
|
||||||
|
'bri': preStrobeOnLightsDataCache[key].state.bri
|
||||||
|
}),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearInterval(this.get('strobeOnInervalHandle'));
|
||||||
|
}
|
||||||
|
}.observes('strobeOn'),
|
||||||
|
|
||||||
|
strobeStep: function () {
|
||||||
|
var lightsData = this.get('lightsData'), lastStrobeLight = (this.get('lastStrobeLight') + 1) % (this.get('numLights') + 1), self = this;
|
||||||
|
|
||||||
|
Em.$.ajax(this.get('lightsApiURL') + '/' + lastStrobeLight + '/state', {
|
||||||
|
data: JSON.stringify({'on': true, 'transitiontime': 0, 'alert': 'select'}),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
Em.$.ajax(self.get('lightsApiURL') + '/' + lastStrobeLight + '/state', {
|
||||||
|
data: JSON.stringify({'on': false, 'transitiontime': 0}),
|
||||||
|
contentType: 'application/json',
|
||||||
|
type: 'PUT'
|
||||||
|
});
|
||||||
|
|
||||||
|
this.set('lastStrobeLight', lastStrobeLight);
|
||||||
|
},
|
||||||
|
|
||||||
|
strobeOnTxt: function () {
|
||||||
|
return this.get('strobeOn') ? 'On' : 'Off';
|
||||||
|
}.property('strobeOn')
|
||||||
|
});
|
||||||
|
|
@ -10,11 +10,20 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
md-switch {
|
.md-subheader-content {
|
||||||
display: inline-flex;
|
max-width: 500px;
|
||||||
margin: 0;
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.controlTxt {
|
md-list {
|
||||||
margin-top: 20px;
|
max-width: 600px;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
max-width: 400px;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
|
{{#paper-list}}
|
||||||
|
|
||||||
{{#each lightsList as |light|}}
|
{{controls/lights-control lightsApiURL=lightsApiURL lightsData=lightsData}}
|
||||||
<img width="40" src="assets/images/lights/{{light}}.svg">
|
|
||||||
{{/each}}
|
|
||||||
|
|
||||||
<div class="controlTxt">Lights:</div>
|
{{paper-divider}}
|
||||||
{{#paper-switch checked=lightsOn}} {{lightsOnTxt}} {{/paper-switch}}
|
|
||||||
|
|
||||||
<div class="controlTxt">Brightness:</div>
|
{{controls/party-control lightsApiURL=lightsApiURL lightsData=lightsData numLights=numLights}}
|
||||||
{{paper-slider flex=true min='1' max='254' value=lightsBrightness disabled=brightnessControlDisabled}}
|
|
||||||
|
{{/paper-list}}
|
||||||
19
app/templates/components/controls/lights-control.hbs
Normal file
19
app/templates/components/controls/lights-control.hbs
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{{#paper-subheader class="md-no-sticky"}}Lights{{/paper-subheader}}
|
||||||
|
|
||||||
|
{{#paper-item class="item"}}
|
||||||
|
{{#each lightsList as |light|}}
|
||||||
|
<img width="40" src="assets/images/lights/{{light}}.svg">
|
||||||
|
{{/each}}
|
||||||
|
{{/paper-item}}
|
||||||
|
|
||||||
|
{{#paper-item class="item"}}
|
||||||
|
{{paper-icon icon="power-settings-new"}}
|
||||||
|
<p>Light:</p>
|
||||||
|
{{#paper-switch checked=lightsOn}} {{lightsOnTxt}} {{/paper-switch}}
|
||||||
|
{{/paper-item}}
|
||||||
|
|
||||||
|
{{#paper-item class="item"}}
|
||||||
|
{{paper-icon icon="brightness-4"}}
|
||||||
|
<p>Brightness</p>
|
||||||
|
{{paper-slider flex=true min='1' max='254' value=lightsBrightness disabled=brightnessControlDisabled}}
|
||||||
|
{{/paper-item}}
|
||||||
13
app/templates/components/controls/party-control.hbs
Normal file
13
app/templates/components/controls/party-control.hbs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{{#paper-subheader class="md-no-sticky"}}Party{{/paper-subheader}}
|
||||||
|
|
||||||
|
{{#paper-item class="item"}}
|
||||||
|
{{paper-icon icon="flare"}}
|
||||||
|
<p>Strobe</p>
|
||||||
|
{{#paper-switch checked=strobeOn}} {{strobeOnTxt}} {{/paper-switch}}
|
||||||
|
{{/paper-item}}
|
||||||
|
|
||||||
|
{{#paper-item class="item"}}
|
||||||
|
{{paper-icon icon="music-note"}}
|
||||||
|
<p>Music</p>
|
||||||
|
{{#paper-button raised=true primary=true}}UPLOAD{{/paper-button}}
|
||||||
|
{{/paper-item}}
|
||||||
0
vendor/.gitkeep
vendored
0
vendor/.gitkeep
vendored
1107
vendor/dancer.js
vendored
Normal file
1107
vendor/dancer.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
Reference in a new issue