All posts by fountside

Philips Hue Entertainment setup and testing

Now that Philips has launched its Entertainment facility for the Hue lights, it’s time to implement and test the features.

What is Entertainment?

It’s a new method for the Bulbs to communicate, meaning that light effects and changes can be synchronised to the split second. This means that the bulbs can react to films, broadcasts, games and music without any lag.  The instructions are sent out in bursts and then carried out all at the same time by the bulbs themselves.  This, in the purest form, means that the bulbs are truly “smart”.

Setting an Entertainment area

You need to tell Hue where your entertainment area(s) are.  An entertainment area is a collection of lights that you want to join together when you’re doing an activity that will use Hue Entertainment – such as playing a video game or watching a film.  You set this up through the Hue app.  Open the app, go to Settings (the gears icon) then choose Entertainment areas.

Select a room or rooms where the entertainment area is to be set up.

HueEnt-01

Select the lights that will be used in your entertainment area.  Notice that Hue recommends the ones that will work best with this feature.  The recommended ones have increased range for brightness and can also show all colours more vividly.

HueEnt-02

Your selected lights appear on a pretend ‘map’ of your entertainment area.  Drag each one into where it is physically positioned in the room.  As you drag, the light in your room will flash so you know which one you are moving on the screen.  Each one will turn from orange to green once you have moved it.

HueEnt-03

When you have positioned the lights on the screen to match where they are, press Test area.

HueEnt-04

The lights will all change colour at the same time, to match the colours showing on the app.

HueEnt-05

Finally, the app will flash each light separately.

Once set up, the area is stored in the bridge’s memory for use later.  At this time the bridge also works out which bulb in the entertainment area should be used as the first point of contact to send out messages to the other bulbs in the area.  You can change this in the app but the automatic decision seems to work well.

Testing the Entertainment area

At the time of writing this entry, there is only one Entertainment partner available on the app – this is Razer hardware (a gaming hardware company).  However, there’s another way to test your new Entertainment area.

A reddit user called CrustaceanSoup has developed a Windows app called Huestacean which can be downloaded and run easily.  The app samples what is displayed on the screen and then converts this to colours in the entertainment area.  For example, you can watch a film or a YouTube video on your computer and your Hue lights sync perfectly to the action on screen.

Thoughts

Thanks to people like CrustaceanSoup we can see the potential for this amazing immersive experience.  The level of synchronicity takes my breath away.

I cannot wait to see how other partners join in with this.  More than merely matching what is on screen, I can see streamed films coming with encoded Hue light programs and live broadcasts sending their stage lighting to Hue to recreate in your living room.

For now, I would be really happy if Hue extended their already strong partnership with Apple and brought a similar screen-mirroring function to the Apple TV, this would mean that practically everything we watch could be extended outwards into the whole living room.

Advertisements

Creating a custom HTML front end for Domoticz Part 4 – YouTube companion article

You can click here for the related YouTube video.

My previous front end for Domoticz was very well received, thank you to everyone who asked for a copy or gave feedback.  I was encouraged to create a simpler to implement but still good-looking design.

The new look is based upon primarily grey and black, with the occasional flash of red or green.  This scheme can be changed easily in the css file of course.  The whole front end has been designed to look great on landscape tablets and portrait smartphones alike.

The front end has been primarily designed to work closely with Domoticz and has several options to insert onto the screen.  The options have been specifically designed to look different to each other even though through Domoticz they would look very much the same.  This is because people who do not routinely use Domoticz generally prefer a little variation in their screen to help them navigate functions.

The functions that look different are:

Feedback switch: Lights up a segment to the right when switch is on and remains dark when off.  Can be pressed anywhere to toggle the switch.

Non-feedback button: A large button which (usually) will switch on a Domoticz switch.  Can be used to activate things like scenes or timed functions such as heating boost.

Temperature / Humidity: Shows in readable text the status of a multifunction sensor.

Sensor: Provides colour feedback on the status of the sensor as well as data on when the sensor was last seen by the system (so for door sensors and doorbells etc this shows the last time the item was used).

Navigation bar: Shows icons which are used to help the user group and navigate across the web app.  Icons were obtained from Flaticon.com and therefore without providing different icons this code cannot be used for commercial gain.

The screen is set up in two ways depending on the orientation of the screen.

Landscape – used for tablet installations: the main section is to the left, with groups of switches in a smaller column to the right.

Portrait – used on smartphones: main screen is at the top of the visible screen, with groups of switches or sensors at the rear of the screen, provided in two columns.

The code is available to download and improve over on github at https://github.com/fountside/domoticz-tiles-user-interface  so you can access copies whenever you like.  You will need the css and at least one html page to get started, then use the elements and change the variables stated at the beginning of the page to match your own setup.  I would encourage anyone who improves this code to publish it within the repository so that others (including me!) can benefit from it.

From feedback I have recently received from readers and YouTube followers, it looks like Domoticz requires the security protocols to be in place, and this version has security built in.  You’ll need to convert your username and password into base64 (follow the instructions on the Domoticz page https://www.domoticz.com/wiki/Domoticz_API/JSON_URL’s to do this).

The only additional type of html document is specifically for Sonos using node-sonos-http-api.  If you already use this then all you’ll need to do is change the variables at the start of the HTML in the audio.htm file to match your rooms set up.  From this screen you can directly control individual rooms (click on the room name to change) and there is a clear graphical display showing album art.  You can launch your favourites and skip tracks.

I hope that this design work and code is of use to you, it is the next iteration of a long-term project of mine to design a near-perfect user interface for the smart home.

 

Creating a custom HTML front end for Domotiz Part 3 – YouTube companion article

We’re going to get a bit more clever now. When we have taught Domoticz a list of devices (be they switches or lights or door contacts) we may want to list them all in one go without manually entering a long list of html for each device. Also, if we can get the HTML front end to gather all the information about each switch, it means that we can update the contents of the buttons automatically, for example if we change the name of a device, it will automatically update in the HTML front end.

I’ve created some code to do this and the commentary on this is over on my YouTube video.

Here’s the code and two css files that you’ll need. Please note that the css files contain more than is needed at the moment: however the css will be needed in future articles.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<head>
<title>Home Control</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />

<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
	<link rel="shortcut icon" href="favicon.ico" />
	<link rel="apple-touch-icon" href="iphone-icon.png"/>
	<link rel="icon" sizes="196x196" href="logo.png">
	<link rel="icon" sizes="192x192" href="logo192.png">
	<link rel="stylesheet" media="(orientation: portrait)" href="portrait.css">
	<link rel="stylesheet" media="(orientation: landscape)" href="landscape.css">
	<link href="https://fonts.googleapis.com/css?family=Baloo|Comfortaa" rel="stylesheet">

<script language="JavaScript" type="text/JavaScript">
<!--
<!--

var devicestodisplay =[36,35,31,141,32,134,132,29,136,140,33,1617];
var nod=0;
var domoticzurl="192.168.1.163";
var domoticzport="8080";

function speak(textToSpeak) {
 // Create a new instance of SpeechSynthesisUtterance
 var newUtterance = new SpeechSynthesisUtterance();

 // Set the text
 newUtterance.text = textToSpeak;

 // Add this text to the utterance queue
 window.speechSynthesis.speak(newUtterance);
}

function switchon(devicecode){
 execute('PUT', 'http://'+domoticzurl+':'+domoticzport+'/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=On', '');
}

function switchoff(devicecode){
 execute('PUT', 'http://'+domoticzurl+':'+domoticzport+'/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Off', '');
}

function toggle(devicecode){
 execute('PUT', 'http://'+domoticzurl+':'+domoticzport+'/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Toggle', '');
}

function dim(devicecode,dimlevel){
 execute('PUT', 'http://'+domoticzurl+':'+domoticzport+'/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Set%20Level&level='+dimlevel, '');
}


function execute($method,$url,$message){
xmlhttp=new XMLHttpRequest();
xmlhttp.open($method,$url,true)
xmlhttp.send($message);
}
window.onload = function() {
 // all of your code goes in here
 // it runs after the DOM is built

 //updateweather();
 getalldevices();
 updatealldevices();
 }
 
window.setInterval(function(){
 updatealldevices();
 }, 1000);



function updatedevice(idx){
 var location="DEVICE"+idx;
 console.log("checking status of idx "+idx);
 var xmlhttp = new XMLHttpRequest();
 var url = 'http://'+domoticzurl+':'+domoticzport+'/json.htm?type=devices&rid='+idx;
 var onoff;
 xmlhttp.onreadystatechange = function() {
 if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
 var myArr = JSON.parse(xmlhttp.responseText);
 onoff = myArr.result[0].Status;
 devicename = myArr.result[0].Name;
 // myFunction(myArr);
 document.getElementById(location).innerHTML='<span class="device">'+devicename+'</span>';
 }
 if (onoff == "On") {
 document.getElementById(location).style.background = "red";
 } 
 if (onoff == "Off") {
 document.getElementById(location).style.background = "grey";
 }
 if (onoff == "Open") {
 document.getElementById(location).style.background = "red";
 } 
 if (onoff == "Closed") {
 document.getElementById(location).style.background = "grey";
 }
 }
xmlhttp.open("GET", url, true);
xmlhttp.send();
}

function getalldevices(){
fLen = devicestodisplay.length;
for (i = 0; i < fLen; i++) {
 preparediv(devicestodisplay[i]);
 getdevice(devicestodisplay[i]);
 }
}

function preparediv(deviceidx){
nod=nod+1;
var div = document.createElement("div");
div.className = 'devicecontainer';
div.id = "DEVICE"+deviceidx;
document.getElementById("devicesdiv").appendChild(div);
}

function updatealldevices(){
fLen = devicestodisplay.length;
for (i = 0; i < fLen; i++) {
 updatedevice(devicestodisplay[i]);
 }
}

function getdevice(idx){
 console.log("getting device idx" + idx);
 var xmlhttp = new XMLHttpRequest();
 var url = "http://"+domoticzurl+":"+domoticzport+"/json.htm?type=devices&rid="+idx;
 xmlhttp.onreadystatechange = function() {
 console.log(devicestodisplay[i] + " " +xmlhttp.readyState)
 if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
 var myArr = JSON.parse(xmlhttp.responseText);
 devicename = myArr.result[0].Name;
 devicestatus = myArr.result[0].Status;
 console.log(devicename + "(" + devicestatus+")");
 adddevice(idx,devicename,devicestatus);
 }
 }
xmlhttp.open("GET", url, true);
xmlhttp.send();
}

function adddevice(deviceidx,devicenametext,devicestatus){
nod=nod+1;
var div = document.createElement("div");
//div.style.width = "100px";
//div.style.height = "100px";
//div.style.background = "red";
//div.style.color = "white";
div.className = 'devicecontainer';
div.innerHTML = devicenametext;
div.id = "DEVICE"+deviceidx;

if (devicestatus=="On"){
 div.style.background = "red";
}

if (devicestatus=="Open"){
 div.style.background = "red";
}

if (devicestatus=="Off"){
 div.style.background = "grey";
}

if (devicestatus=="Closed"){
 div.style.background = "grey";
}

console.log("-------------"+div.id);
//document.getElementById("devicesdiv").appendChild(div);
document.getElementById(div.id).addEventListener('click', function() {
 { toggle(deviceidx); };
}, false);
}

function myFunction(arr) {
 var out = "";
 out += arr[0].result.Status;
 document.getElementById("id01").innerHTML = out;
}

//-->
</script>


<body>

<audio id="scene" src="assets/sounds/beep2.mp3" preload="auto"></audio>
<div align="left" class="toplinks">
<a href="index.htm"><span class="menutext">Home</span></a>
<a href="lights.htm"><span class="menutext">Lights</span></a>
<a href="devices.htm"><span class="menutext">Devices</span></a>
<a href="audiotrial.htm"><span class="menutext">Audio</span></a>
<a href="climate.htm"><span class="menutext">Environment</span></a>
<a href="security.htm"><span class="menutext">Security</span></a>
<a href="activities.htm"><span class="menutext">Other screens</span></a></div>
<div id="notification" align="center" class="notificationpane" onClick="clearnotification(11);"></div>
<div id="devicesdiv"></div>
</body>
</html>

Here’s the landscape.css file


body {
background-color:#000000;
font-family: 'Comfortaa', sans-serif;
margin: 0 0 0 0;
padding: 0 0 0 0 ;
}

.back-to-top {
background: none;
margin: 0;
position: fixed;
bottom: 50px;
right: 20px;
width: 150px;
height: 50px;
z-index: 100;
display: none;
text-decoration: none;
}

.back-to-top i {
font-size: 60px;
}

.timerselecttext {
font-size: 60px;
color:#FFFFFF;
}

.clockdisplay {
font-size: 250px;
color:grey;
}

div.clocktext {
font-size: 100px;
color:#000000;
}

div.weathertext {
font-size: 70px;
color:#000000;
}


div.standardcontainer {
background-color:grey;
position:relative;
width:25%;
height:25vh;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 4vw;
text-align:center;
box-shadow:inset 0px 0px 0px 1px black;
}

div.doublecontainer {
background-color:grey;
position:relative;
width:50%;
height:25vh;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 4vw;
text-align:center;
box-shadow:inset 0px 0px 0px 1px black;
}

div.devicecontainer {
background-color:grey;
width:25%;
height:12vh;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 2vw;
box-shadow:inset 0px 0px 0px 1px black;
}


div.albumcontainer {
width:28vw;
height:28vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.trackcontainer {
width:70vw;
height:10vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.audiocontrols {
background-color:grey;
width:100vw;
height:10vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.audioactivitycontainer {

width:70vw;
height:10vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.camera {
background-color:grey;
width:100vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.camcontrols {
background-color:green;
width:300px;
float:right;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

span {
background-color: #ffffff;
color: #75099b;
font-size:20px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

div.nightclock {
background-color:#333333;
position:relative;
width:100%;
float:left;
padding-top:10px;
overflow:auto;
color:#666666;
font-size: 5vw;
text-align:center;
box-shadow:inset 0px 0px 0px 1px black;
}

span.title {
background-color:#666666;
color:#FFFFFF;
font-size:35px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.timertext {
background-color:green;
color:#FFFFFF;
font-size:70px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.playstate {
background-color:green;
color:#FFFFFF;
font-size:12px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.temptext {
background-color:green;
color:#FFFFFF;
font-size:40px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.roomname {
background-color:green;
color:#FFFFFF;
font-size:40px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.lightroom {
background-color:green;
color:#FFFFFF;
font-size:30px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}


span.device {
background-color:#666666;
color:#FFFFFF;
font-size:20px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.sensor {
background-color:#666666;
color:#FFFFFF;
font-size:18px;
display: inline-block;
padding: 3px 10px;
margin: 0px 5px;
font-weight: bold;
border-radius: 5px;
}


span.screentitle {
background-color:#666666;
font-family: 'Baloo', sans-serif;
color:#FFFFFF;
font-size:30px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
border-radius: 5px;
}

span.menutext {
background-color:#0066FF;
color:#FFFFFF;
font-size:24px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.datetime {
background-color:#009900;
color:#FFFFFF;
font-size:16px;
display: inline-block;
padding: 5px 5px;
margin: 0px 5px;
border-radius: 5px;
}


div.audioroomcontainer {
background-color:#66FF99;
float:left;
height:200px;
padding-top:10px;
overflow:auto;
font-size: 25px;
margin: 0 0 10px 10px;
}

div.nightmodecontainer {
background-color:#666666;
width:150px;
float:left;
height:200px;
padding-top:10px;
overflow:auto;
font-size: 25px;
margin: 0 0 10px 10px;
}


div.notificationpane {
background-color:#FFFFCC;
width:100%;
font-size: 2.5vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.nightnotificationpane {
background-color:grey;
width:100%;
font-size: 2.5vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.toplinks {
background-color:#66CCFF;
top:0px;
left:0px;
width:100%;
font-size: 30px;
box-shadow:inset 0px 0px 0px 1px black;
}

div.popuppanel {
background-color:grey;
width:100vw;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

and here’s the portrait.css file


body {
background-color:#000000;
font-family: 'Comfortaa', sans-serif;
margin: 0 0 0 0;
padding: 0 0 0 0 ;
}

.back-to-top {
background: none;
margin: 0;
position: fixed;
bottom: 50px;
right: 20px;
width: 150px;
height: 50px;
z-index: 100;
display: none;
text-decoration: none;
}

.back-to-top i {
font-size: 60px;
}

.timerselecttext {
font-size: 60px;
color:#FFFFFF;
}

.clockdisplay {
font-size: 200px;
color:#000000;
}

div.clocktext {
font-size: 100px;
color:#000000;
}

div.weathertext {
font-size: 70px;
color:#000000;
}


div.nightclock {
background-color:#333333;
position:relative;
width:100%;
float:left;
padding-top:10px;
overflow:auto;
color:#666666;
font-size: 5vw;
text-align:center;
box-shadow:inset 0px 0px 0px 1px black;
}

div.doublecontainer {
background-color:grey;
position:relative;
width:100%;
height:25vh;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 4vw;
text-align:center;
box-shadow:inset 0px 0px 0px 1px black;
}

div.standardcontainer {
background-color:grey;
position:relative;
width:50%;
height:15vh;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 2vw;
text-align:center;
box-shadow:inset 0px 0px 0px 1px black;
}

div.nightclock {
background-color:#333333;
position:relative;
width:100%;
float:left;
padding-top:10px;
overflow:auto;
color:#666666;
font-size: 5vw;
text-align:center;
box-shadow:inset 0px 0px 0px 1px black;
}

div.devicecontainer {
background-color:grey;
width:50%;
height:10vh;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 2vw;
box-shadow:inset 0px 0px 0px 1px black;
}


div.albumcontainer {
background-color:grey;
width:100vw;
height:100vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.trackcontainer {
background-color:grey;
width:100vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.audiocontrols {
background-color:grey;
width:100vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.audioactivitycontainer {
background-color:grey;
width:100vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.camera {
background-color:grey;
width:100vw;
float:left;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

div.camcontrols {
background-color:green;
width:100vw;
float:right;
padding-top:0px;
color:white;
font-size: 3vw;
box-shadow:inset 0px 0px 0px 1px black;
}

span.menutext {
background-color: #ffffff;
color: #75099b;
font-size:3vw;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span {
background-color: #ffffff;
color: #75099b;
font-size:18px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.title {
background-color:#666666;
color:#FFFFFF;
font-size:18px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.timertext {
background-color:green;
color:#FFFFFF;
font-size:20px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.lightroom {
background-color:green;
color:#FFFFFF;
font-size:16px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}
span.temptext {
background-color:green;
color:#FFFFFF;
font-size:20px;
display: inline-block;
padding: 10px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}
span.device {
background-color:#666666;
color:#FFFFFF;
font-size:18px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.screentitle {
background-color:#666666;
font-family: 'Baloo', sans-serif;
color:#FFFFFF;
font-size:18px;
display: inline-block;
padding: 5px 5px;
margin: 5px;
border-radius: 5px;
}


span.menutext {
background-color:#0066FF;
color:#FFFFFF;
font-size:24px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.datetime {
background-color:#009900;
color:#FFFFFF;
font-size:12px;
display: inline-block;
padding: 5px 5px;
margin: 0px 5px;
border-radius: 5px;
}

span.sensor {
background-color:#666666;
color:#FFFFFF;
font-size:14px;
display: inline-block;
padding: 3px 10px;
margin: 0px 5px;
font-weight: bold;
border-radius: 5px;
}

div.audioroomcontainer {
background-color:#66FF99;
float:left;
height:200px;
padding-top:10px;
overflow:auto;
font-size: 25px;
margin: 0 0 10px 10px;
}

div.nightmodecontainer {
background-color:#666666;
width:150px;
float:left;
height:200px;
padding-top:10px;
overflow:auto;
font-size: 25px;
margin: 0 0 10px 10px;
}


div.notificationpane {
background-color:#FFFFCC;
width:100%;
font-size: 16px;
box-shadow:inset 0px 0px 0px 1px black;
}


div.toplinks {
background-color:#66CCFF;
top:0px;
left:0px;
width:100%;
font-size: 30px;
overflow:scroll;
box-shadow:inset 0px 0px 0px 1px black;
}

div.popuppanel {
background-color:grey;
width:100vw;
float:left;
padding-top:10px;
overflow:auto;
color:white;
font-size: 2vw;
box-shadow:inset 0px 0px 0px 1px black;
}

Creating a custom HTML front end for Domoticz part 2 – YouTube companion article

This article just shows the code that accompanies the next in the multi-part series explaining how I created my (reasonably popular!) HTML front end.

The icon I used can be downloaded from Flaticon.com but remember to download two versions, one you should rename dehumidifier-on.png and one dehumidifier-off.png

Here’s the code.

index.htm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<head>
<title>Home Control</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
		<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
		<meta name="apple-mobile-web-app-capable" content="yes" />
		<meta name="mobile-web-app-capable" content="yes" />
		<meta name="apple-mobile-web-app-status-bar-style" content="black" />

		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<meta name="description" content="" />
		<meta name="keywords" content="" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
			<link rel="shortcut icon" href="favicon.ico" />
			<link rel="apple-touch-icon" href="iphone-icon.png"/>
			<link rel="icon" sizes="196x196" href="logo.png">
			<link rel="icon" sizes="192x192" href="logo192.png">
			<link rel="stylesheet" media="(orientation: portrait)" href="portrait.css">
			<link rel="stylesheet" media="(orientation: landscape)" href="landscape.css">

  	<link href="https://fonts.googleapis.com/css?family=Baloo|Comfortaa" rel="stylesheet">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<script language="JavaScript" type="text/JavaScript">

var domoticzurl="192.168.1.163"

function MM_goToURL() { //v3.0
  var i, args=MM_goToURL.arguments; document.MM_returnValue = false;
  for (i=0; i<(args.length-1); i+=2) eval(args[i]+".location='"+args[i+1]+"'");
}
function speak(textToSpeak) {
   // Create a new instance of SpeechSynthesisUtterance
   var newUtterance = new SpeechSynthesisUtterance();

   // Set the text
   newUtterance.text = textToSpeak;

   // Add this text to the utterance queue
   window.speechSynthesis.speak(newUtterance);
}

function switchon(devicecode){
	execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=On', '');
}

function switchoff(devicecode){
	execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Off', '');
}

function toggle(devicecode){
	execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Toggle', '');
}

function dim(devicecode,dimlevel){
	execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Set%20Level&level='+dimlevel, '');
}


function execute($method,$url,$message){
xmlhttp=new XMLHttpRequest();
xmlhttp.open($method,$url,true)
xmlhttp.send($message);
}

function toggleDiv(divId) {
   $("#"+divId).toggle(100);
}

function hideDiv(divId) {
   $("#"+divId).hide();
}
	
window.addEventListener("load", function(){
});;

function hideallDivs() {
    hideDiv("lights");
	hideDiv("devices");
}

//the following functions will run every second (due to the 1000 at the end).
window.setInterval(function(){
	updatedevice(36,'dehumidifier',"dehumidifier-on.png","dehumidifier-off.png");
	}, 1000);


// the following function checks to see if the idx is "on" or "off" and updates the image accordingly
function updatedevice(idx,location,onimage,offimage){
	console.log("checking status of idx "+idx);
	var xmlhttp = new XMLHttpRequest();
	var url = "http://"+domoticzurl+":8080/json.htm?type=devices&rid="+idx;
	var onoff;
	xmlhttp.onreadystatechange = function() {
    	if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        	var myArr = JSON.parse(xmlhttp.responseText);
			onoff = myArr.result[0].Status;
       // myFunction(myArr);
    	}
		if (onoff == "On") {
		document.getElementById(location).src = onimage;
		} 
		if (onoff == "Off") {
		document.getElementById(location).src = offimage;
		}
		if (onoff == "Open") {
		document.getElementById(location).src = onimage;
		} 
		if (onoff == "Closed") {
		document.getElementById(location).src = offimage;
		}
	}
xmlhttp.open("GET", url, true);
xmlhttp.send();
}


</script>

</head>

<body>

<a href="javascript:;"  onclick="toggleDiv('lights');"><span class="navtitle">Lights</span></a>
<div id="lights" class="navlights">
Desk Lamp

<a href="javascript:;" onclick="dim(594,16);toggleDiv('lights');"><span class="buttontext">Max</span></a>
<a href="javascript:;" onclick="dim(594,12);toggleDiv('lights');"><span class="buttontext">75%</span></a>
<a href="javascript:;" onclick="dim(594,8);toggleDiv('lights');"><span class="buttontext">50%</span></a>
<a href="javascript:;" onclick="dim(594,4);toggleDiv('lights');"><span class="buttontext">25%</span></a>
<a href="javascript:;" onclick="switchoff(594);toggleDiv('lights');"><span class="buttontext">Off</span></a>

<hr width="90%" style="dashed" color="#FFFFFF" size="2">

Ceiling Lamp

<a href="javascript:;" onclick="dim(81,100);toggleDiv('lights');"><span class="buttontext">Max</span></a>
<a href="javascript:;" onclick="dim(81,75);toggleDiv('lights');"><span class="buttontext">75%</span></a>
<a href="javascript:;" onclick="dim(81,50);toggleDiv('lights');"><span class="buttontext">50%</span></a>
<a href="javascript:;" onclick="dim(81,25);toggleDiv('lights');"><span class="buttontext">25%</span></a>
<a href="javascript:;" onclick="switchoff(81);toggleDiv('lights');"><span class="buttontext">Off</span></a></div>
<a href="javascript:;"  onclick="toggleDiv('devices');"><span class="navtitle">Devices</span></a>
<div id="devices" class="navlights">
Dehumidifier

<a href="javascript:;" onclick="toggle(36);"><img id="dehumidifier" src="dehumidifier-off.png"></a></div>
</body>

And here are the 2 css sheets you need (I don’t know why I have done this yet but these will be useful when we start looking at device orientation.

Portrait.css

html {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
background-color:#000000;
}
div.navlights {
display:block;
text-align:center;
position:relative;
width: 100vw;
margin:0vw;
background-color:#CCCCCC;
font-family: 'Comfortaa', cursive;
font-size:6vw;
font-color:#000000;
}
span.buttontext {
background-color: #ffffff;
color: #75099b;
font-size:6vw;
display: inline-block;
padding: 3px 10px;
margin: 1vw;
font-weight: bold;
border-radius: 5px;
}

span.toggletext {
background-color: #FF66CC;
color:#ffffff;
font-size:6vw;
display: inline-block;
padding: 3px 10px;
margin: 1vw;
font-weight: bold;
border-radius: 5px;
}

span.navtitle {
color: #FFFFFF;
font-size:5vw;
display: inline-block;
margin: 3vw;
font-family: 'Baloo',cursive;
font-weight: normal;
}

landscape.css

html {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
background-color:#000000;
}
div.navlights {
display:block;
text-align:center;
position:relative;
width: 100vw;
margin:0vw;
background-color:#CCCCCC;
font-family: 'Comfortaa', cursive;
font-size:40px;
font-color:#000000;
}
span.buttontext {
background-color: #ffffff;
color: #75099b;
font-size:36px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.toggletext {
background-color: #FF66CC;
color:#ffffff;
font-size:36px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.navtitle {
color: #FFFFFF;
font-size:50px;
display: inline-block;
margin: 5px;
font-family: 'Baloo',cursive;
font-weight: normal;
}

 

Creating a custom HTML front end for Domoticz Part 1- YouTube companion article

ere’s the HTML and CSS you’ll need if you want to follow my guide over on my YouTube channel on how to create a custom user interface using HTML for Domoticz.

I’ve been asked many times for the code for my HTML interface and others have asked how to develop their own, so this step by step guide should help you to build a great looking interface that you can be proud of, and your family can use with ease.

In the index.htm file, when copied into a text editor, change the line:

var domoticzurl="192.168.1.163"

to the address of your Domoticz system.

Go to the Domoticz folder, then to the www folder, then create a folder called whatever you want your creation to be called.  I’ve called the folder fab for now.

Copy the three files into the folder.  Once complete, the Domoticz HTML server will serve up the page to whomever requests it.

Try it out by opening any browser and typing in

addressofyourdomoticzsystem:port/yourfoldername/index.htm

In my case this would be

192.168.1.200:8080/fab/index.htm

If all is well you should see your masterpiece!  Have a go at changing the names and idx codes of the devices and re-uploading and testing again.

As this HTML code sends HTTP requests, your browser may ask if you want to enable content.  This has happened on my desktop version of Google Chrome a few times.

There is some code at the top of the index.htm page that tells your browser that if you’re using a smartphone to open this page, you can save it to your homescreen.  The next time you open it, there will be no address bar and it will look like a web app.

save this text as index.htm


 


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<head>
<title>Home Control</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />

<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<link rel="shortcut icon" href="favicon.ico" />
		<link rel="apple-touch-icon" href="iphone-icon.png"/>
		<link rel="icon" sizes="196x196" href="logo.png">
		<link rel="icon" sizes="192x192" href="logo192.png">
		<link rel="stylesheet" media="(orientation: portrait)" href="portrait.css">
		<link rel="stylesheet" media="(orientation: landscape)" href="landscape.css">

		<link href="https://fonts.googleapis.com/css?family=Baloo|Comfortaa" rel="stylesheet">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

<script language="JavaScript" type="text/JavaScript">

var domoticzurl="192.168.1.163"

function MM_goToURL() { //v3.0
 var i, args=MM_goToURL.arguments; document.MM_returnValue = false;
 for (i=0; i<(args.length-1); i+=2) eval(args[i]+".location='"+args[i+1]+"'");
}
function speak(textToSpeak) {
 // Create a new instance of SpeechSynthesisUtterance
 var newUtterance = new SpeechSynthesisUtterance();

// Set the text
 newUtterance.text = textToSpeak;

// Add this text to the utterance queue
 window.speechSynthesis.speak(newUtterance);
}

function switchon(devicecode){
 execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=On', '');
}

function switchoff(devicecode){
 execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Off', '');
}

function toggle(devicecode){
 execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Toggle', '');
}

function dim(devicecode,dimlevel){
 execute('PUT', 'http://' + domoticzurl + ':8080/json.htm?type=command&param=switchlight&idx='+devicecode+'&switchcmd=Set%20Level&level='+dimlevel, '');
}

function execute($method,$url,$message){
xmlhttp=new XMLHttpRequest();
xmlhttp.open($method,$url,true)
xmlhttp.send($message);
}

function toggleDiv(divId) {
 $("#"+divId).toggle(100);
}

function hideDiv(divId) {
 $("#"+divId).hide();
}

window.addEventListener("load", function(){
 hideallDivs();
});;

function hideallDivs() {
 hideDiv("lights");
 hideDiv("devices");
}

</script>

</head>

<body>

<a href="javascript:;" onclick="toggleDiv('lights');"><span class="navtitle">Lights</span></a>
<div id="lights" class="navlights">
Desk Lamp

<a href="javascript:;" onclick="dim(594,16);toggleDiv('lights');"><span class="buttontext">Max</span></a>
<a href="javascript:;" onclick="dim(594,12);toggleDiv('lights');"><span class="buttontext">75%</span></a>
<a href="javascript:;" onclick="dim(594,8);toggleDiv('lights');"><span class="buttontext">50%</span></a>
<a href="javascript:;" onclick="dim(594,4);toggleDiv('lights');"><span class="buttontext">25%</span></a>
<a href="javascript:;" onclick="switchoff(594);toggleDiv('lights');"><span class="buttontext">Off</span></a>

<hr width="90%" style="dashed" color="#FFFFFF" size="2">

Ceiling Lamp

<a href="javascript:;" onclick="dim(81,100);toggleDiv('lights');"><span class="buttontext">Max</span></a>
<a href="javascript:;" onclick="dim(81,75);toggleDiv('lights');"><span class="buttontext">75%</span></a>
<a href="javascript:;" onclick="dim(81,50);toggleDiv('lights');"><span class="buttontext">50%</span></a>
<a href="javascript:;" onclick="dim(81,25);toggleDiv('lights');"><span class="buttontext">25%</span></a>
<a href="javascript:;" onclick="switchoff(81);toggleDiv('lights');"><span class="buttontext">Off</span></a></div>
<a href="javascript:;" onclick="toggleDiv('devices');"><span class="navtitle">Devices</span></a>
<div id="devices" class="navlights">
Dehumidifier

<a href="javascript:;" onclick="switchon(29);toggleDiv('devices');"><span class="buttontext">On</span></a>
<a href="javascript:;" onclick="switchoff(29);toggleDiv('devices');"><span class="buttontext">Off</span></a>
<a href="javascript:;" onclick="toggleDiv('devices');"><span class="toggletext">Auto</span></a></div>
</body>


Save this text as portrait.css


html {
margin: 0;
padding: 0;
}

body {
margin: 0;
padding: 0;
background-color:#000000;
}

div.navlights {
display:block;
text-align:center;
position:relative;
width: 100vw;
margin:0vw;
background-color:#CCCCCC;
font-family: 'Comfortaa', cursive;
font-size:6vw;
font-color:#000000;
}

span.buttontext {
background-color: #ffffff;
color: #75099b;
font-size:6vw;
display: inline-block;
padding: 3px 10px;
margin: 1vw;
font-weight: bold;
border-radius: 5px;
}

span.toggletext {
background-color: #FF66CC;
color:#ffffff;
font-size:6vw;
display: inline-block;
padding: 3px 10px;
margin: 1vw;
font-weight: bold;
border-radius: 5px;
}

span.navtitle {
color: #FFFFFF;
font-size:5vw;
display: inline-block;
margin: 3vw;
font-family: 'Baloo',cursive;
font-weight: normal;
}


And finally save this as landscape.css


html {
margin: 0;
padding: 0;
}

body {
margin: 0;
padding: 0;
background-color:#000000;
}

div.navlights {
display:block;
text-align:center;
position:relative;
width: 100vw;
margin:0vw;
background-color:#CCCCCC;
font-family: 'Comfortaa', cursive;
font-size:40px;
font-color:#000000;
}

span.buttontext {
background-color: #ffffff;
color: #75099b;
font-size:36px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.toggletext {
background-color: #FF66CC;
color:#ffffff;
font-size:36px;
display: inline-block;
padding: 3px 10px;
margin: 5px;
font-weight: bold;
border-radius: 5px;
}

span.navtitle {
color: #FFFFFF;
font-size:50px;
display: inline-block;
margin: 5px;
font-family: 'Baloo',cursive;
font-weight: normal;
}

Philips Hue in partnership with The Voice UK will bring the studio into your living room

I don’t think I have ever been more excited about Philips Hue, and that is saying something as I am a great lover of the whole range of products.

In January ITV (the UK television network) announced that during later stages of The Voice UK, the companion app will control connected Hue devices and sync them to the stage lighting.  This means in effect that the lighting director will not only be controlling the stage where the contestants sing, but also the lights wherever you are watching.

I have downloaded the app in anticipation and have selected the lights I want to be controlled during the live performance, and also tested the setup via a short sample video supplied in the app.  If the live shows sync up as well as the sample video did, I can only tremble with anticipation before the live head-to-head shows begin.

THIS is what we have been waiting for.  Ambilight and the projection version of Ambilight from Philips proved that extending the lighting effects beyond the visible window you can see on television creates a much more immersive experience.  This new innovation (similar – but possibly an evolution of – the SyFy Sync app)  brings us one step closer to all action/music/performance programmes having “light encoding” similar to the way subtitles are currently saved alongside video.  I cannot wait to see this in action: Philips, if you are reading this and you need a “real” home to preview The Voice integration: pick me!

Podcast interview

I was interviewed for the David Snape and Friends podcast last week.  David’s blog and podcast is an eclectic mix showcasing bloggers’ hidden talents.  It’s a great read and I would recommend you having a look.

The interview was tailored mainly as an introduction to smart homes and so may be a bit basic for enthusiasts who already have a knowledge of how devices fit together. If you’re interested in listening please go to the podcast’s page (my interview starts at 1 hour 31 minutes and lasts about 20 minutes).

I’ve been concentrating on my new YouTube channel for the last few weeks but I’m not ignoring my blog:  I have a few entries planned out including some simple Lua scripts to whet your appetites.  I am also working on a new user interface for smart home control (what’s new!) so I will be showcasing that soon and I will hopefully have a place for you to download it directly.