Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
becburne committed Dec 3, 2021
2 parents 455a513 + d05af9c commit 9b3e6ae
Show file tree
Hide file tree
Showing 23 changed files with 965 additions and 40 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
2 changes: 2 additions & 0 deletions Philips Hue/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ui-builder.js
ui.js
59 changes: 59 additions & 0 deletions Philips Hue/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Philips Hue

Easily discover and connect to your Philips Hue ecosystem and control individual lights
or groups/rooms from your Webex device.

<!-- ![Quiet Mode](quietmode.png) -->

## Description


Nice if you want to:

* Control the light in your home office or other rooms without opening your phone
* Make the lights react to events on your device, such as incoming call, meeting starting
* Show others you busy / in-call by making an indicator lamp red
* Set the light color to match your virtual background, for a more realistic view
* Control other peripherals in your home with the Philips Hue Smart Plug


## Customise it yourself

This extension let's you easily connect to the Hue bridge and create a stanard user interface for you lights,
using UI Extensions. However, you may want to customize the user interface to exact purpose. You can do quite a
lot without any programming by adding UI extensions that giving the specific widget ids.

The widget will automatically control a specified light or group by having a widget id that matches this format:

```
huectrl-<id>-<controltype>
```

Where id is either light id or group id. Control type can be:

```
on: set power on or off (typically from switch)
toggle: toggle power to opposite (typically from push button)
bri: brightness (use slider)
col: color hue (slider or button group)
sat: color saturation (slider or button group)
```

Example: A home screen button to quickly toggle on/off a single light or room

* Add an **action button** from the UI extensions
* To toggle light #7, give id the panel id **huectrl-7-on**
* To toggle brightness for light #3, give the slider widget id **huectrl-3-bri**


## Requirements

* CE 9.1 or greater
* Supported on both Touch 10 and devices with touch screen, such as Desk Pro and the Webex Board
* Philips Hue bridge
* Video device on same network as Hue bridge (or at least reachable)
* Philips Hue bridge and lights already configured (eg from phone app)

## Note

This macro uses the `xConfig FacilityService[4] Name` to store the user's preferences, so you should not install it if you are using facility service actively on your device.
5 changes: 5 additions & 0 deletions Philips Hue/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# TODO

* Documentation on github
* Add support for color temperature
* Possible to enter bridge ip manually (for office)
22 changes: 22 additions & 0 deletions Philips Hue/examples/incall-indicator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const xapi = require('xapi');
const Hue = require('../hue-lib');

const hue = new Hue();

const inCallLamp = 6; // hue id for light to indicate in-call state

async function callStateChanged() {
const calls = await xapi.Status.SystemUnit.State.NumberOfActiveCalls.get();
if (calls > 0) {
const state = hue.Colors.red;
state.on = true;
hue.setLightState(inCallLamp, state);
}
else {
hue.setLightState(inCallLamp, hue.Colors.white);
}
}

hue.loadConfig();
xapi.Status.SystemUnit.State.NumberOfActiveCalls.on(callStateChanged);
callStateChanged();
23 changes: 23 additions & 0 deletions Philips Hue/examples/incoming-call-blink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const xapi = require('xapi');
const Hue = require('../hue-lib');

const hue = new Hue();

const lightId = 6; // hue id for light to indicate in-call state
const blinks = 6;

function incomingCall() {
let i = 0;
function blink() {
if (i < blinks) {
hue.blink(lightId);
setTimeout(blink, 1000);
}
i++;
}

blink();
}

hue.loadConfig();
xapi.Event.IncomingCallIndication.on(incomingCall);
22 changes: 22 additions & 0 deletions Philips Hue/examples/presence-indicator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const xapi = require('xapi');
const Hue = require('../hue-lib');

const hue = new Hue();

const presenceLamp = 6; // hue id for lamp to indicate people presence


// requires xConfiguration RoomAnalytics PeoplePresenceDetector to be on
async function presenceChanged() {
const present = await xapi.Status.RoomAnalytics.PeoplePresence.get();
console.log('present', present);
if (present === 'Unknown') return;
else {
const color = present === 'Yes' ? hue.Colors.red : hue.Colors.green;
hue.setLightState(presenceLamp, Object.assign({ on: true }, color));
}
}

hue.loadConfig();
xapi.Status.RoomAnalytics.PeoplePresence.on(presenceChanged);
presenceChanged();
20 changes: 20 additions & 0 deletions Philips Hue/examples/temperature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const xapi = require('xapi');
const Hue = require('../hue-lib');

const hue = new Hue();

const temperaturePlug = 6; // hue id for device to toggle fan
const temperatureThreshold = 21.5;

async function pollTemperature() {
try {
const temp = await xapi.Status.RoomAnalytics.AmbientTemperature.get()
const tooWarm = temp > temperatureThreshold;
console.log(temp);
hue.setLightState(temperaturePlug, { on: tooWarm });
}
catch(e) {} // not all devices support it
}

hue.loadConfig();
setInterval(pollTemperature, 1000 * 5);
53 changes: 53 additions & 0 deletions Philips Hue/examples/virtual-background-panel.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<Extensions>
<Version>1.5</Version>
<Panel>
<Order>4</Order>
<PanelId>virtual-background</PanelId>
<Type>Home</Type>
<Icon>Tv</Icon>
<Color>#C233C4</Color>
<Name>Virtual Background</Name>
<ActivityType>Custom</ActivityType>
<Page>
<Name>Virtual Background</Name>
<Row>
<Name>Select Background</Name>
<Widget>
<WidgetId>virtual-background</WidgetId>
<Type>GroupButton</Type>
<Options>size=4</Options>
<ValueSpace>
<Value>
<Key>User1</Key>
<Name>Fireplace</Name>
</Value>
<Value>
<Key>User2</Key>
<Name>Ocean</Name>
</Value>
<Value>
<Key>User3</Key>
<Name>Jungle</Name>
</Value>
</ValueSpace>
</Widget>
</Row>
<Row>
<Name/>
<Widget>
<WidgetId>virtual-background-download</WidgetId>
<Name>Download images</Name>
<Type>Button</Type>
<Options>size=2</Options>
</Widget>
<Widget>
<WidgetId>virtual-background-delete</WidgetId>
<Name>Delete</Name>
<Type>Button</Type>
<Options>size=2</Options>
</Widget>
</Row>
<Options/>
</Page>
</Panel>
</Extensions>
68 changes: 68 additions & 0 deletions Philips Hue/examples/virtual-background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const xapi = require('xapi');
const Hue = require('../hue-lib');

const hue = new Hue();

const presenceLamp = 6; // hue id for lamp to indicate people presence

const images = {
User1: {
id: 'fireplace',
url: 'https://images.unsplash.com/photo-1586997641337-63f21b02591e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80',
color: { hue: 8371, sat: 254 },
},
User2: {
id: 'ocean',
url: 'https://images.unsplash.com/photo-1468581264429-2548ef9eb732?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2670&q=80',
color: { hue: 43530, sat: 226 },
},
User3: {
id: 'jungle',
url: 'https://images.unsplash.com/photo-1470058869958-2a77ade41c02?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2670&q=80',
color: { hue:29251, sat: 207},
},
};

function changeBg(id) {
xapi.Command.Cameras.Background.Set({ Image: id, Mode: 'Image' });
const color = images[id].color;
hue.setLightState(presenceLamp, color);
}

async function downloadImages() {
for (const id in images) {
const { url } = images[id];
xapi.Command.UserInterface.Message.Alert.Display({ Text: 'Downloading virtual bg: ' + id});
await xapi.Command.Cameras.Background.Fetch({
Url: url, Image: id,
});
}
xapi.Command.UserInterface.Message.Alert.Display({ Text: 'Image download complete', Duration: 3 });
}

async function deleteImages() {
for (const id in images) {
await xapi.Command.Cameras.Background.Delete({ Image: id });
}
xapi.Command.UserInterface.Message.Alert.Display({ Text: 'Virtual images deleted', Duration: 3 });
}

async function init() {
await hue.loadConfig();
xapi.Event.UserInterface.Extensions.Widget.Action.on(e => {
if (e.WidgetId === 'virtual-background' && e.Type === 'released') {
changeBg(e.Value);
}
else if (e.WidgetId === 'virtual-background-download' && e.Type === 'clicked') {
downloadImages();
}
else if (e.WidgetId === 'virtual-background-delete' && e.Type === 'clicked') {
deleteImages();
}

});
const light = (await hue.getLightState())[presenceLamp].state;
console.log({ hue: light.hue, sat: light.sat });
}

init();
Loading

0 comments on commit 9b3e6ae

Please sign in to comment.