sample_pir-lights_rgb

Dependencies:   ChainableLED

Committer:
iv123
Date:
Sun Jun 18 10:14:56 2017 +0000
Revision:
0:7a352727249b
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
iv123 0:7a352727249b 1 <!DOCTYPE html>
iv123 0:7a352727249b 2 <html>
iv123 0:7a352727249b 3 <head>
iv123 0:7a352727249b 4 <meta charset="utf-8">
iv123 0:7a352727249b 5 <title>Light System</title>
iv123 0:7a352727249b 6 <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,600' rel='stylesheet' type='text/css'>
iv123 0:7a352727249b 7 <link rel="stylesheet" href="/style.css">
iv123 0:7a352727249b 8 <link rel="import" href="/color-picker-element/dist/color-picker.html">
iv123 0:7a352727249b 9 <link rel="manifest" href="/manifest.json">
iv123 0:7a352727249b 10 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
iv123 0:7a352727249b 11 </head>
iv123 0:7a352727249b 12
iv123 0:7a352727249b 13 <body>
iv123 0:7a352727249b 14 <div id="header">
iv123 0:7a352727249b 15 <a href="/"><img id="logo" src="/ARMmbedLogo.svg"></a>
iv123 0:7a352727249b 16 </div>
iv123 0:7a352727249b 17
iv123 0:7a352727249b 18 <h1>Lights</h1>
iv123 0:7a352727249b 19
iv123 0:7a352727249b 20 <ul id="lights">
iv123 0:7a352727249b 21 {{#devices}}
iv123 0:7a352727249b 22 {{> device}}
iv123 0:7a352727249b 23 {{/devices}}
iv123 0:7a352727249b 24 </ul>
iv123 0:7a352727249b 25
iv123 0:7a352727249b 26 <div id="color-picker-overlay" style="display: none">
iv123 0:7a352727249b 27 <h2>Change color</h2>
iv123 0:7a352727249b 28 </div>
iv123 0:7a352727249b 29 <div id="notification" style="opacity: 0; visibility: hidden;"></div>
iv123 0:7a352727249b 30
iv123 0:7a352727249b 31 <script src="/helper-functions.js"></script>
iv123 0:7a352727249b 32 <script src="/color-picker.js"></script>
iv123 0:7a352727249b 33 <script src="/socket.io/socket.io.js"></script>
iv123 0:7a352727249b 34 <script>
iv123 0:7a352727249b 35 /*global io getElement updateStatusUi getDeviceName showNotification localStorage */
iv123 0:7a352727249b 36
iv123 0:7a352727249b 37 // Here is how we connect back to the server
iv123 0:7a352727249b 38 var socket = io.connect(location.origin);
iv123 0:7a352727249b 39
iv123 0:7a352727249b 40 // ==== BEGIN SERVER EVENTS ====
iv123 0:7a352727249b 41
iv123 0:7a352727249b 42 var createDeviceEv, deleteDeviceEv, changeStatusEv, changeColorEv, changeTimeoutEv;
iv123 0:7a352727249b 43
iv123 0:7a352727249b 44 // Device came online, add it to the UI
iv123 0:7a352727249b 45 socket.on('created-device', createDeviceEv = function(viewModel) {
iv123 0:7a352727249b 46 document.querySelector('#lights').insertAdjacentHTML('beforeend', viewModel.html);
iv123 0:7a352727249b 47 });
iv123 0:7a352727249b 48
iv123 0:7a352727249b 49 // Device was deleted, remove it from the UI
iv123 0:7a352727249b 50 socket.on('deleted-device', deleteDeviceEv = function(endpoint) {
iv123 0:7a352727249b 51 var li = getElement(endpoint);
iv123 0:7a352727249b 52 li.parentNode.removeChild(li);
iv123 0:7a352727249b 53
iv123 0:7a352727249b 54 showNotification(getDeviceName(endpoint, true) + ' was de-registered');
iv123 0:7a352727249b 55 });
iv123 0:7a352727249b 56
iv123 0:7a352727249b 57 // Status of a device was updated
iv123 0:7a352727249b 58 socket.on('change-status', changeStatusEv = function(endpoint, status) {
iv123 0:7a352727249b 59 updateStatusUi(endpoint, status);
iv123 0:7a352727249b 60 });
iv123 0:7a352727249b 61
iv123 0:7a352727249b 62 // Color of a device was updated
iv123 0:7a352727249b 63 socket.on('change-color', changeColorEv = function(endpoint, color) {
iv123 0:7a352727249b 64 var hex = Number(color).toString(16);
iv123 0:7a352727249b 65 getElement(endpoint).querySelector('.color').style.backgroundColor =
iv123 0:7a352727249b 66 '#' + '000000'.substring(0, 6 - hex.length) + hex;
iv123 0:7a352727249b 67 });
iv123 0:7a352727249b 68
iv123 0:7a352727249b 69 // Timeout of a device was updated
iv123 0:7a352727249b 70 socket.on('change-timeout', changeTimeoutEv = function(endpoint, timeout) {
iv123 0:7a352727249b 71 getElement(endpoint).querySelector('.change-timeout').textContent =
iv123 0:7a352727249b 72 timeout + ' seconds';
iv123 0:7a352727249b 73 });
iv123 0:7a352727249b 74
iv123 0:7a352727249b 75 // When you go offline=>online, server will automatically send current state
iv123 0:7a352727249b 76 // So you're always up to date with other clients.
iv123 0:7a352727249b 77 socket.on('device-list', function(list) {
iv123 0:7a352727249b 78 list.forEach(function(device) {
iv123 0:7a352727249b 79 // element not in the UI yet? Create it!
iv123 0:7a352727249b 80 if (!getElement(device.endpoint)) {
iv123 0:7a352727249b 81 return createDeviceEv(device.view);
iv123 0:7a352727249b 82 }
iv123 0:7a352727249b 83
iv123 0:7a352727249b 84 // otherwise, update the properties
iv123 0:7a352727249b 85 changeStatusEv(device.endpoint, device.view.model.status);
iv123 0:7a352727249b 86 changeColorEv(device.endpoint, device.view.model.rawColor);
iv123 0:7a352727249b 87 changeTimeoutEv(device.endpoint, device.view.model.timeout);
iv123 0:7a352727249b 88 });
iv123 0:7a352727249b 89
iv123 0:7a352727249b 90 // find devices that are still in the UI, but no longer in the list...
iv123 0:7a352727249b 91 var validEndpoints = list.map(function(device) { return device.endpoint; });
iv123 0:7a352727249b 92 [].forEach.call(document.querySelectorAll('li[data-endpoint]'), function(li) {
iv123 0:7a352727249b 93 if (validEndpoints.indexOf(li.dataset.endpoint) === -1) {
iv123 0:7a352727249b 94 deleteDeviceEv(li.dataset.endpoint);
iv123 0:7a352727249b 95 }
iv123 0:7a352727249b 96 });
iv123 0:7a352727249b 97
iv123 0:7a352727249b 98 });
iv123 0:7a352727249b 99
iv123 0:7a352727249b 100 // ==== END OF SERVER EVENTS ====
iv123 0:7a352727249b 101
iv123 0:7a352727249b 102
iv123 0:7a352727249b 103
iv123 0:7a352727249b 104 // ==== BEGIN UI EVENTS ====
iv123 0:7a352727249b 105
iv123 0:7a352727249b 106 // When someone clicks on an element in the device area...
iv123 0:7a352727249b 107 document.querySelector('#lights').addEventListener('click', function(e) {
iv123 0:7a352727249b 108
iv123 0:7a352727249b 109 // We look at which endpoint we're clicking on...
iv123 0:7a352727249b 110 var parent = e.target;
iv123 0:7a352727249b 111 while (e.target.parentElement && !((parent = parent.parentElement).dataset.endpoint)) {
iv123 0:7a352727249b 112 // noop
iv123 0:7a352727249b 113 }
iv123 0:7a352727249b 114 if (!parent.dataset.endpoint) return console.error('Could not find parent for', e.target);
iv123 0:7a352727249b 115
iv123 0:7a352727249b 116 var endpoint = parent.dataset.endpoint;
iv123 0:7a352727249b 117
iv123 0:7a352727249b 118 // Now we can check which element we clicked on:
iv123 0:7a352727249b 119 if (e.target.classList.contains('change-timeout')) {
iv123 0:7a352727249b 120 changeTimeout(endpoint, e.target);
iv123 0:7a352727249b 121 return false;
iv123 0:7a352727249b 122 }
iv123 0:7a352727249b 123
iv123 0:7a352727249b 124 if (e.target.classList.contains('change-status')) {
iv123 0:7a352727249b 125 changeStatus(endpoint, e.target);
iv123 0:7a352727249b 126 return false;
iv123 0:7a352727249b 127 }
iv123 0:7a352727249b 128
iv123 0:7a352727249b 129 // Names are stored locally...
iv123 0:7a352727249b 130 if (e.target.classList.contains('change-endpoint-name')) {
iv123 0:7a352727249b 131 var n = prompt('Enter new name');
iv123 0:7a352727249b 132 if (n) {
iv123 0:7a352727249b 133 e.target.textContent = n;
iv123 0:7a352727249b 134 localStorage.setItem(endpoint + '-name', n);
iv123 0:7a352727249b 135 }
iv123 0:7a352727249b 136 else if (n === '') {
iv123 0:7a352727249b 137 e.target.textContent = endpoint;
iv123 0:7a352727249b 138 localStorage.setItem(endpoint + '-name', '');
iv123 0:7a352727249b 139 }
iv123 0:7a352727249b 140 return false;
iv123 0:7a352727249b 141 }
iv123 0:7a352727249b 142
iv123 0:7a352727249b 143 // Click on color => show color picker
iv123 0:7a352727249b 144 if (e.target.classList.contains('color')) {
iv123 0:7a352727249b 145 var cp = document.querySelector('#color-picker-overlay');
iv123 0:7a352727249b 146 cp.dataset.endpoint = endpoint;
iv123 0:7a352727249b 147 cp.style.display = 'flex';
iv123 0:7a352727249b 148 return false;
iv123 0:7a352727249b 149 }
iv123 0:7a352727249b 150 });
iv123 0:7a352727249b 151
iv123 0:7a352727249b 152 // ==== END UI EVENTS ====
iv123 0:7a352727249b 153
iv123 0:7a352727249b 154
iv123 0:7a352727249b 155
iv123 0:7a352727249b 156 // ==== BEGIN UI ACTIONS ====
iv123 0:7a352727249b 157
iv123 0:7a352727249b 158 function changeTimeout(endpoint, el) {
iv123 0:7a352727249b 159 var old = el.textContent.split(' ')[0];
iv123 0:7a352727249b 160
iv123 0:7a352727249b 161 // Ask for a new value and verify that it's a number
iv123 0:7a352727249b 162 var v = prompt('Enter a new value for the motion timeout');
iv123 0:7a352727249b 163 if (v === false) return;
iv123 0:7a352727249b 164 if (!v || isNaN(v)) {
iv123 0:7a352727249b 165 return showNotification('Updating timeout failed: not a number');
iv123 0:7a352727249b 166 }
iv123 0:7a352727249b 167
iv123 0:7a352727249b 168 // Update the UI
iv123 0:7a352727249b 169 el.textContent = v + ' seconds';
iv123 0:7a352727249b 170 // Send to the server
iv123 0:7a352727249b 171 socket.emit('change-timeout', endpoint, Number(v), function(err) {
iv123 0:7a352727249b 172 // If it fails, reset to old value and show notification
iv123 0:7a352727249b 173 if (err) {
iv123 0:7a352727249b 174 el.textContent = old + ' seconds';
iv123 0:7a352727249b 175 showNotification('Updating timeout failed: ' + err);
iv123 0:7a352727249b 176 }
iv123 0:7a352727249b 177 });
iv123 0:7a352727249b 178 }
iv123 0:7a352727249b 179
iv123 0:7a352727249b 180 function changeStatus(endpoint, el) {
iv123 0:7a352727249b 181 // get the currently selected value
iv123 0:7a352727249b 182 var old = el.parentNode.querySelector('.selected').dataset.action;
iv123 0:7a352727249b 183
iv123 0:7a352727249b 184 // update the UI
iv123 0:7a352727249b 185 updateStatusUi(endpoint, el.dataset.action);
iv123 0:7a352727249b 186
iv123 0:7a352727249b 187 // send to server
iv123 0:7a352727249b 188 socket.emit('change-status', endpoint, Number(el.dataset.action), function(err) {
iv123 0:7a352727249b 189 // if it fails, reset to old value and show notification
iv123 0:7a352727249b 190 if (err) {
iv123 0:7a352727249b 191 updateStatusUi(endpoint, old);
iv123 0:7a352727249b 192 showNotification('Updating status failed: ' + err);
iv123 0:7a352727249b 193 }
iv123 0:7a352727249b 194 });
iv123 0:7a352727249b 195 }
iv123 0:7a352727249b 196
iv123 0:7a352727249b 197 function changeColor(endpoint, newColor) {
iv123 0:7a352727249b 198 var colorEl = getElement(endpoint).querySelector('.color');
iv123 0:7a352727249b 199 var oldHex = Number(colorEl.dataset.value).toString(16);
iv123 0:7a352727249b 200 var newHex = Number(newColor).toString(16);
iv123 0:7a352727249b 201
iv123 0:7a352727249b 202 if (newColor === 0) return;
iv123 0:7a352727249b 203
iv123 0:7a352727249b 204 console.log('new value is', newColor);
iv123 0:7a352727249b 205
iv123 0:7a352727249b 206 // Update UI
iv123 0:7a352727249b 207 colorEl.style.backgroundColor = '#' + '000000'.substring(0, 6 - newHex.length) + newHex;
iv123 0:7a352727249b 208
iv123 0:7a352727249b 209 // Send to server
iv123 0:7a352727249b 210 socket.emit('change-color', endpoint, newColor, function(err) {
iv123 0:7a352727249b 211 // If all fails, reset back to old color
iv123 0:7a352727249b 212 if (err) {
iv123 0:7a352727249b 213 colorEl.style.backgroundColor = '#' + '000000'.substring(0, 6 - oldHex.length) + oldHex;
iv123 0:7a352727249b 214 showNotification('Updating color failed: ' + err);
iv123 0:7a352727249b 215 }
iv123 0:7a352727249b 216 });
iv123 0:7a352727249b 217 }
iv123 0:7a352727249b 218
iv123 0:7a352727249b 219 // ==== END UI ACTIONS ====
iv123 0:7a352727249b 220
iv123 0:7a352727249b 221 </script>
iv123 0:7a352727249b 222
iv123 0:7a352727249b 223 </body>
iv123 0:7a352727249b 224 </html>