diff --git a/front/build/asset-manifest.json b/front/build/asset-manifest.json
index c3063771f..e2794c36f 100644
--- a/front/build/asset-manifest.json
+++ b/front/build/asset-manifest.json
@@ -1,14 +1,14 @@
{
"files": {
"main.css": "/static/css/main.2d15d020.chunk.css",
- "main.js": "/static/js/main.f5e71cab.chunk.js",
- "main.js.map": "/static/js/main.f5e71cab.chunk.js.map",
+ "main.js": "/static/js/main.6564749c.chunk.js",
+ "main.js.map": "/static/js/main.6564749c.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.db8f2875.js",
"runtime-main.js.map": "/static/js/runtime-main.db8f2875.js.map",
"static/js/2.b6bfd886.chunk.js": "/static/js/2.b6bfd886.chunk.js",
"static/js/2.b6bfd886.chunk.js.map": "/static/js/2.b6bfd886.chunk.js.map",
"index.html": "/index.html",
- "precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js": "/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js",
+ "precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js": "/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js",
"service-worker.js": "/service-worker.js",
"static/css/main.2d15d020.chunk.css.map": "/static/css/main.2d15d020.chunk.css.map",
"static/js/2.b6bfd886.chunk.js.LICENSE.txt": "/static/js/2.b6bfd886.chunk.js.LICENSE.txt"
@@ -17,6 +17,6 @@
"static/js/runtime-main.db8f2875.js",
"static/js/2.b6bfd886.chunk.js",
"static/css/main.2d15d020.chunk.css",
- "static/js/main.f5e71cab.chunk.js"
+ "static/js/main.6564749c.chunk.js"
]
}
\ No newline at end of file
diff --git a/front/build/index.html b/front/build/index.html
index a4761d85f..f3f47d644 100644
--- a/front/build/index.html
+++ b/front/build/index.html
@@ -1 +1 @@
-
Homeware-LAN You need to enable JavaScript to run this app.
\ No newline at end of file
+Homeware-LAN You need to enable JavaScript to run this app.
\ No newline at end of file
diff --git a/front/build/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js b/front/build/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js
similarity index 72%
rename from front/build/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js
rename to front/build/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js
index caa089a76..afd0ffd68 100644
--- a/front/build/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js
+++ b/front/build/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js
@@ -1,10 +1,10 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
- "revision": "272c561c9c54b570ba6ff4ee01d5fc9d",
+ "revision": "0e341a28acee7a6a5733c503eaca59bf",
"url": "/index.html"
},
{
- "revision": "c7b8bd7a8e25bf695c7a",
+ "revision": "bdca616ef5c466f85a3d",
"url": "/static/css/main.2d15d020.chunk.css"
},
{
@@ -16,8 +16,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/js/2.b6bfd886.chunk.js.LICENSE.txt"
},
{
- "revision": "c7b8bd7a8e25bf695c7a",
- "url": "/static/js/main.f5e71cab.chunk.js"
+ "revision": "bdca616ef5c466f85a3d",
+ "url": "/static/js/main.6564749c.chunk.js"
},
{
"revision": "ef13c11e300e1acbb1b7",
diff --git a/front/build/service-worker.js b/front/build/service-worker.js
index 9f2dc17dc..11e5ff24c 100644
--- a/front/build/service-worker.js
+++ b/front/build/service-worker.js
@@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
- "/precache-manifest.f6516c056036507f2e00fe494f9e0d7a.js"
+ "/precache-manifest.92352c6ecf63a4676b0a3ef3a7b5b2a8.js"
);
self.addEventListener('message', (event) => {
diff --git a/front/build/static/js/main.6564749c.chunk.js b/front/build/static/js/main.6564749c.chunk.js
new file mode 100644
index 000000000..db588a4b7
--- /dev/null
+++ b/front/build/static/js/main.6564749c.chunk.js
@@ -0,0 +1,2 @@
+(this.webpackJsonpHomeware=this.webpackJsonpHomeware||[]).push([[0],{13:function(e,t,a){},139:function(e,t,a){"use strict";a.r(t);var i=a(0),n=a.n(i),s=a(40),r=a.n(s),c=(a(48),a(1)),l=a(2),o=a(5),d=a(4),m=a(3),u=(a(49),a(41)),p=a(7);var v=function(e){for(var t=e+"=",a=decodeURIComponent(document.cookie).split(";"),i=0;i"),n.a.createElement("option",null,"<="),n.a.createElement("option",null,">=")))),i,n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTriggerOperation},"Save"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel")))}}]),a}(n.a.Component),Ae=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={device_a:"",device_b:""},i.updateDependencies=i.updateDependencies.bind(Object(o.a)(i)),i.addTriggerOperation=i.addTriggerOperation.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"updateDependencies",value:function(e){var t=this.state;t[e.target.id]=e.target.value,this.setState(t)}},{key:"addTriggerOperation",value:function(){var e=document.getElementById("device_a").value+":"+document.getElementById("param_a").value+":"+document.getElementById("comparator").value+":"+document.getElementById("device_b").value+":"+document.getElementById("param_b").value;this.props.addTriggerOperation("d2d",e),this.props.closeTriggerAssistant()}},{key:"render",value:function(){var e=this,t=Object.keys(this.props.devices).map((function(t){return n.a.createElement("option",{key:t,value:t},e.props.devices[t])})),a=""===this.state.device_a?"":Object.keys(this.props.status[this.state.device_a]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")})),i=""===this.state.device_b?"":Object.keys(this.props.status[this.state.device_b]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")}));return n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"Compare two devices"),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device A*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device_a",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param A*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param_a",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a param"),a))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Comparator*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"comparator"},n.a.createElement("option",null,"="),n.a.createElement("option",null,"<"),n.a.createElement("option",null,">"),n.a.createElement("option",null,"<="),n.a.createElement("option",null,">=")))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device B*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device_b",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param B*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param_b",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a param"),i))),n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTriggerOperation},"Save"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel")))}}]),a}(n.a.Component),De=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={type:""},i.timeTigger=i.timeTigger.bind(Object(o.a)(i)),i.deiceTrigger=i.deiceTrigger.bind(Object(o.a)(i)),i.deviceToDeviceTrigger=i.deviceToDeviceTrigger.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"timeTigger",value:function(){this.setState({type:"time"})}},{key:"deiceTrigger",value:function(){this.setState({type:"device"})}},{key:"deviceToDeviceTrigger",value:function(){this.setState({type:"device2device"})}},{key:"render",value:function(){return""===this.state.type?n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"Add a new trigger"),n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.timeTigger},"Time"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.deiceTrigger},"Device"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.deviceToDeviceTrigger},"Device to device"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel"))):"time"===this.state.type?n.a.createElement(Me,{closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):"device"===this.state.type?n.a.createElement(Le,{devices:this.props.devices,status:this.props.status,closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):"device2device"===this.state.type?n.a.createElement(Ae,{devices:this.props.devices,status:this.props.status,closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):void 0}}]),a}(n.a.Component),Ie=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).delete=i.delete.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"delete",value:function(){this.props.delete(this.props.id)}},{key:"render",value:function(){return n.a.createElement("div",{className:"trigger_device_container",style:{marginBottom:"10px"}},n.a.createElement("span",null,(this.props.devices[this.props.target.device]?this.props.devices[this.props.target.device]:this.props.target.device)+" ("+(b.params[this.props.target.param]?b.params[this.props.target.param].name:this.props.target.param)+") = "+this.props.target.value),n.a.createElement("img",{src:"/global/bin_icon.png",alt:"Delete icon",className:"trigger_delete",onClick:this.delete}))}}]),a}(n.a.Component),He=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={device:""},i.updateDevice=i.updateDevice.bind(Object(o.a)(i)),i.updateParam=i.updateParam.bind(Object(o.a)(i)),i.addTarget=i.addTarget.bind(Object(o.a)(i)),i.typeConversion=i.typeConversion.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"updateDevice",value:function(e){this.setState({device:e.target.value})}},{key:"updateParam",value:function(e){this.setState({param:e.target.value})}},{key:"addTarget",value:function(){var e={device:document.getElementById("device").value,param:document.getElementById("param").value,value:document.getElementById("value").value};this.props.addTarget(e),document.getElementById("device").value="",document.getElementById("param").value="",this.setState({param:""})}},{key:"typeConversion",value:function(e){return{int:"d2i",list:"d2l",bool:"d2b",string:"d2s",color:"d2c"}[e]}},{key:"render",value:function(){var e=this,t=Object.keys(this.props.devices).map((function(t){return n.a.createElement("option",{key:t,value:t},e.props.devices[t])})),a=""===this.state.device?"":Object.keys(this.props.status[this.state.device]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")})),i="";if(b.params[this.state.param]){var s=this.typeConversion(b.params[this.state.param].type);if("d2i"===s)i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"number",className:"",id:"value"})));else if("d2s"===s)i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"",id:"value"})));else if("d2b"===s||"d2l"===s){var r=b.params[this.state.param].select.map((function(e){return n.a.createElement("option",{key:e,value:e},e)}));i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"value"},r)))}}return n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"New target"),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device",onChange:this.updateDevice},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param",onChange:this.updateParam},n.a.createElement("option",{value:""},"Select a param"),a))),i,n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTarget},"Add")))}}]),a}(n.a.Component),Pe=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;Object(c.a)(this,a),i=t.call(this,e);var n=window.location.pathname.split("/")[3],s=!1;return""===n&&(s=!0),i.state={id:n,create:s,save_status:"",trigger_assistant_parent:0,task:{title:"",description:"",triggers:{},target:[]},devices:[],status:{}},i.update=i.update.bind(Object(o.a)(i)),i.save=i.save.bind(Object(o.a)(i)),i.delete=i.delete.bind(Object(o.a)(i)),i.deleteTrigger=i.deleteTrigger.bind(Object(o.a)(i)),i.addTriggerLogic=i.addTriggerLogic.bind(Object(o.a)(i)),i.openTriggerAssistant=i.openTriggerAssistant.bind(Object(o.a)(i)),i.addTriggerOperation=i.addTriggerOperation.bind(Object(o.a)(i)),i.closeTriggerAssistant=i.closeTriggerAssistant.bind(Object(o.a)(i)),i.addTarget=i.addTarget.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){var e=new XMLHttpRequest;if(e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText),i={};a.devices.forEach((function(e){i[e.id]=e.name.name})),this.setState({devices:i,status:a.status})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/global/get/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(),!this.state.create){var t=new XMLHttpRequest;t.onload=function(e){if(4===t.readyState)if(200===t.status){var a=JSON.parse(t.responseText);console.log(a),this.setState({task:a})}else console.error(t.statusText)}.bind(this),t.open("GET",h+"api/tasks/get/"+this.state.id+"/"),t.setRequestHeader("authorization","baerer "+v("token")),t.send()}}},{key:"update",value:function(e){var t=this.state.task;t[e.target.id]=e.target.value,this.setState({task:t})}},{key:"save",value:function(){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?(JSON.parse(e.responseText),this.state.create?window.location.href="/tasks":this.setState({save_status:"Saved correctly."})):(console.error(e.statusText),this.setState({save_status:"Error, the changes haven't been saved."})),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this);var t={task:this.state.task};this.state.create?e.open("POST",h+"api/tasks/create/"):(e.open("POST",h+"api/tasks/update/"),t.id=this.state.id),e.setRequestHeader("Content-Type","application/json;charset=UTF-8"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(JSON.stringify(t))}},{key:"delete",value:function(){if(window.confirm("Do you want to delete the task?")){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?window.location.href="/tasks/":(console.error(e.statusText),this.setState({save_status:"Error, the device hasn't been deleted."})),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this),e.open("GET",h+"api/tasks/delete/"+this.state.id+"/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send()}else this.setState({save_status:"Ok. The device is save."})}},{key:"deleteTrigger",value:function(e){var t=this.state.task,a=t.triggers,i=a[e].parent;if("triggers"!==i){var n=a[i].operation.indexOf(e);a[i].operation.splice(n,1),delete a[e],t.triggers=a}else t.triggers={};this.setState({task:t})}},{key:"addTriggerLogic",value:function(e,t){var a=this.state.task;if("triggers"!==t){var i=Date.now();a.triggers[i]={operation:[],parent:t,type:e},a.triggers[t].operation.push(i)}else a.triggers.trigger={operation:[],parent:"triggers",type:e};this.setState({task:a})}},{key:"openTriggerAssistant",value:function(e){this.setState({trigger_assistant_parent:e})}},{key:"addTriggerOperation",value:function(e,t){var a=this.state.task,i=this.state.trigger_assistant_parent;if("triggers"!==i){var n=Date.now();a.triggers[n]={operation:t,parent:i,type:e},a.triggers[i].operation.push(n)}else a.triggers.trigger={operation:t,parent:"triggers",type:e};this.setState({task:a})}},{key:"closeTriggerAssistant",value:function(){this.setState({trigger_assistant_parent:0})}},{key:"addTarget",value:function(e){var t=this.state.task;t.target.push(e),this.setState({task:t})}},{key:"render",value:function(){var e=this,t=this.state.task.target.map((function(t,a){return n.a.createElement(Ie,{key:a,target:t,devices:e.state.devices})}));return n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"Task"),n.a.createElement("hr",{style:{width:"70%"}}),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Name*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"title",defaultValue:this.state.task.title,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Description*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"description",defaultValue:this.state.task.description,onChange:this.update}))),n.a.createElement("hr",null),n.a.createElement("h2",null,"Triggers"),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null)),0!==this.state.trigger_assistant_parent?n.a.createElement(De,{devices:this.state.devices,status:this.state.status,closeTriggerAssistant:this.closeTriggerAssistant,addTriggerOperation:this.addTriggerOperation}):n.a.createElement(Re,{id:"trigger",triggers:this.state.task.triggers,devices:this.state.devices,delete:this.deleteTrigger,addTriggerLogic:this.addTriggerLogic,openTriggerAssistant:this.openTriggerAssistant}),n.a.createElement("hr",null),n.a.createElement("h2",null,"Targets"),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null)),t,n.a.createElement(He,{devices:this.state.devices,status:this.state.status,addTarget:this.addTarget}),n.a.createElement("hr",null),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("button",{type:"button",style:this.state.create?{backgroundColor:"red",opacity:"0.2"}:{backgroundColor:"red"},onClick:this.delete,disabled:!!this.state.create},"Delete"),n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status))))}}]),a}(n.a.Component),Fe=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={settings:{google:{},ddns:{},mqtt:{},apikey:""},save_status:"",url:{auth:"",token:"",fulfillment:""}},i.update=i.update.bind(Object(o.a)(i)),i.enableDdnsProvider=i.enableDdnsProvider.bind(Object(o.a)(i)),i.save=i.save.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){if(!this.state.create){var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText);this.setState({settings:a,url:{auth:"https://"+a.ddns.hostname+"/auth/",token:"https://"+a.ddns.hostname+"/token/",fulfillment:"https://"+a.ddns.hostname+"/smarthome/"}})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/settings/get/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send()}}},{key:"update",value:function(e){var t=e.target.id.split("/"),a=this.state.settings;1===t.length?a[t[0]]=e.target.value:2===t.length&&(a[t[0]][t[1]]=e.target.value),this.setState({settings:a})}},{key:"enableDdnsProvider",value:function(e){var t=this.state.settings;t.ddns.enabled=e,this.setState({settings:t})}},{key:"save",value:function(){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?(JSON.parse(e.responseText),this.setState({save_status:"Saved correctly."})):this.setState({save_status:"Error, the changes haven't been saved."}),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this),e.open("POST",h+"api/settings/update/"),e.setRequestHeader("Content-Type","application/json;charset=UTF-8"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(JSON.stringify(this.state.settings))}},{key:"render",value:function(){return n.a.createElement("div",null,n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"Actions on Google"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Client ID"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"google/client_id",defaultValue:this.state.settings.google.client_id,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Client Secret"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"google/client_secret",defaultValue:this.state.settings.google.client_secret,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Authorization URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.auth,disabled:!0}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Token URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.token,disabled:!0}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Fulfillment URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.fulfillment,disabled:!0})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Actions on Google settings. It is used to authenticate with Google. If you change it here, you must change it on the Actions Console > Develop > Account Linking."))),n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"MQTT"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"User"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"mqtt/user",defaultValue:this.state.settings.mqtt.user,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Password"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"mqtt/password",defaultValue:this.state.settings.mqtt.password,onChange:this.update})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Important. You must configure the username and password into Mosquitto manually from a terminal. This is only for telling Homeware its credentials. Clear both if you don't use credentials."))),n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"DDNS provider"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Status:"),n.a.createElement("div",{className:"two_table_cel"},this.state.settings.ddns.status)),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"IP and time:"),n.a.createElement("div",{className:"two_table_cel"},this.state.settings.ddns.ip+" updated at "+this.state.settings.ddns.last))),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Enable"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement(ie.a,{onChange:this.enableDdnsProvider,checked:this.state.settings.ddns.enabled}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Provider"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"settings_select",id:"ddns/provider",value:this.state.settings.ddns.provider,onChange:this.update},n.a.createElement("option",{value:"noip"},"Noip")))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Username"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/username",defaultValue:this.state.settings.ddns.username,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Password"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/password",defaultValue:this.state.settings.ddns.password,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Hostname"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/hostname",defaultValue:this.state.settings.ddns.hostname,onChange:this.update})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Set up the access data to the DDNS provider account. Open an issue on Github if you want a DDNS provider that is not listed."))))}}]),a}(n.a.Component);var qe=function(e){return n.a.createElement("div",{style:{marginTop:"5px",width:"100%",display:"grid",gridTemplateColumns:"70% 30%"}},n.a.createElement("div",{style:{textAlign:"left",paddingTop:"4px"}},n.a.createElement("span",{style:{fontSize:"18px"}},e.title)),n.a.createElement("div",{style:{textAlign:"right",paddingTop:"4px"}},n.a.createElement("span",{style:"Running"===e.status?{fontSize:"12px",fontWeight:"bold",color:"white",backgroundColor:"green",padding:"5px",paddingLeft:"10px",paddingRight:"10px",borderRadius:"5px"}:{fontSize:"12px",fontWeight:"bold",color:"white",backgroundColor:"red",padding:"5px",paddingLeft:"10px",paddingRight:"10px",borderRadius:"5px"}},e.status)))},Ge=a(54),Ue=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={components:[],git:{version:"",description:"",code:0},version:"",upgrading:!1,show_system_message:!1,system_message:""},i.loadComponents=i.loadComponents.bind(Object(o.a)(i)),i.upgrade=i.upgrade.bind(Object(o.a)(i)),i.areYouAwake=i.areYouAwake.bind(Object(o.a)(i)),i.restart=i.restart.bind(Object(o.a)(i)),i.reboot=i.reboot.bind(Object(o.a)(i)),i.shutdown=i.shutdown.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){this.loadComponents(),setInterval(this.loadComponents,3e3);var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText);this.setState({version:a.version})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/global/version/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send();var t=new XMLHttpRequest;t.onload=function(e){if(4===t.readyState)if(200===t.status){var a=JSON.parse(t.responseText),i=a.body;this.setState({git:{version:a.tag_name,description:i,code:200}})}else 403===t.status?this.setState({git:{version:"GitHub rate limit exceeded. You have reloaded so many times. It will reset after some time.",code:403}}):console.error(t.statusText)}.bind(this),t.open("GET","https://api.github.com/repos/kikeelectronico/Homeware-LAN/releases/latest"),t.send()}},{key:"loadComponents",value:function(){var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){for(var a=JSON.parse(e.responseText),i=[],n=Object.keys(a),s=0;s1&&this.setState({page:this.state.page-1})}},{key:"nextPage",value:function(){this.state.page\n \n
\n
\n \n { props.title } \n
\n \n );\n}\n\nexport default Menu\n","import React from 'react';\nimport getCookieValue from '../../../functions'\nimport { root } from '../../../constants'\n\nclass OnOff extends React.Component {\n constructor(props) {\n super(props);\n this.toggle = this.toggle.bind(this);\n }\n\n toggle(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n this.props.reload();\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this)\n http.open(\"POST\", root + \"api/status/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify({\n \"id\": this.props.id,\n \"param\": \"on\",\n \"value\": !this.props.on\n }));\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default OnOff\n","import React from 'react';\n\nclass Information extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/info/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default Information\n","import React from 'react';\n\nclass Connecting extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/connecting/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default Connecting\n","import React from 'react';\n\nclass Edit extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/editor/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default Edit\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Light extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\" && Object.keys(this.props.status).includes(\"color\"))){\n if (Object.keys(this.props.status.color).includes(\"spectrumRgb\"))\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n else\n color = \"#\" + this.props.status.color.spectrumRGB.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Light\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Outlet extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'blue',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Outlet\n","import React from 'react';\nimport getCookieValue from '../../../functions'\nimport { root } from '../../../constants'\n\nclass TemperatureSetting extends React.Component {\n constructor(props) {\n super(props);\n this.up = this.up.bind(this);\n this.down = this.down.bind(this);\n this.update = this.update.bind(this);\n }\n\n up(){\n var temperature = this.props.status.thermostatTemperatureSetpoint + 1;\n this.update(temperature)\n }\n\n down(){\n var temperature = this.props.status.thermostatTemperatureSetpoint - 1;\n this.update(temperature)\n }\n\n update(temperature){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n this.props.reload();\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this)\n http.open(\"POST\", root + \"api/status/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify({\n \"id\": this.props.id,\n \"param\": \"thermostatTemperatureSetpoint\",\n \"value\": temperature\n }));\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n const temperature = {\n fontSize: '30px',\n marginLeft: '5px',\n marginRight: '5px',\n color: '#777'\n }\n\n return (\n \n
\n
{this.props.status.thermostatTemperatureSetpoint} \n
\n
\n );\n }\n}\n\nexport default TemperatureSetting\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport TemperatureSetting from './traits/TemperatureSetting'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AcUnit extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.status.thermostatMode === 'off')\n color = \"#666\";\n else if (this.props.status.thermostatMode === 'heat')\n color = \"red\";\n else if (this.props.status.thermostatMode === 'cool')\n color = \"lightblue\";\n else if (this.props.status.thermostatMode === 'on')\n color = \"yellow\";\n else if (this.props.status.thermostatMode === 'heatcool')\n color = \"#DC97FF\";\n else if (this.props.status.thermostatMode === 'auto')\n color = \"#EE357E\";\n else if (this.props.status.thermostatMode === 'fan-only')\n color = \"blue\";\n else if (this.props.status.thermostatMode === 'purifier')\n color = \"#F3882E\";\n else if (this.props.status.thermostatMode === 'eco')\n color = \"green\";\n else if (this.props.status.thermostatMode === 'dry')\n color = \"#753500\";\n\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AcUnit\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirFreshener extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirFreshener\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirPurifier extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirPurifier\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Bed extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Bed\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Fan extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Fan\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Fireplace extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Fireplace\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Radiator extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Radiator\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Switch extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Switch\n","import React from 'react';\nimport TemperatureSetting from './traits/TemperatureSetting'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Thermostat extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.status.thermostatMode === 'off')\n color = \"#666\";\n else if (this.props.status.thermostatMode === 'heat')\n color = \"red\";\n else if (this.props.status.thermostatMode === 'cool')\n color = \"lightblue\";\n else if (this.props.status.thermostatMode === 'on')\n color = \"yellow\";\n else if (this.props.status.thermostatMode === 'heatcool')\n color = \"#DC97FF\";\n else if (this.props.status.thermostatMode === 'auto')\n color = \"#EE357E\";\n else if (this.props.status.thermostatMode === 'fan-only')\n color = \"blue\";\n else if (this.props.status.thermostatMode === 'purifier')\n color = \"#F3882E\";\n else if (this.props.status.thermostatMode === 'eco')\n color = \"green\";\n else if (this.props.status.thermostatMode === 'dry')\n color = \"#753500\";\n\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Thermostat\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirCooler extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirCooler\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Bathtub extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Bathtub\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Awing extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Awing\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Blinds extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Blinds\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Closet extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Closet\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Curtain extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Curtain\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Door extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Door\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Drawer extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Drawer\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Garage extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Garage\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Pergola extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Pergola\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Shutter extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Shutter\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Valve extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Valve\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Window extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Window\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Lock extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Lock\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Gate extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Gate\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Heater extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Heater\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Hood extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Hood\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass SecuritySystem extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default SecuritySystem\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Blender extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Blender\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Global extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'white';\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Global\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Scene extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'white';\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n \n
\n
\n
Scene: { this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Scene\n","import React from 'react';\nimport Light from '../devices/Light'\nimport Outlet from '../devices/Outlet'\nimport AcUnit from '../devices/AcUnit'\nimport AirFreshener from '../devices/AirFreshener'\nimport AirPurifier from '../devices/AirPurifier'\nimport Bed from '../devices/Bed'\nimport Fan from '../devices/Fan'\nimport Fireplace from '../devices/Fireplace'\nimport Radiator from '../devices/Radiator'\nimport Switch from '../devices/Switch'\nimport Thermostat from '../devices/Thermostat'\nimport AirCooler from '../devices/AirCooler'\nimport Bathtub from '../devices/Bathtub'\nimport Awing from '../devices/Awing'\nimport Blinds from '../devices/Blinds'\nimport Closet from '../devices/Closet'\nimport Curtain from '../devices/Curtain'\nimport Door from '../devices/Door'\nimport Drawer from '../devices/Drawer'\nimport Garage from '../devices/Garage'\nimport Pergola from '../devices/Pergola'\nimport Shutter from '../devices/Shutter'\nimport Valve from '../devices/Valve'\nimport Window from '../devices/Window'\nimport Lock from '../devices/Lock'\nimport Gate from '../devices/Gate'\nimport Heater from '../devices/Heater'\nimport Hood from '../devices/Hood'\nimport SecuritySystem from '../devices/SecuritySystem'\nimport Blender from '../devices/Blender'\nimport Global from '../devices/Global'\nimport Scene from '../devices/Scene'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Devices.css';\n\nclass Devices extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: {},\n devices: []\n }\n this.loadData = this.loadData.bind(this);\n this.newDevice = this.newDevice.bind(this);\n }\n\n componentDidMount() {\n this.loadData();\n setInterval(this.loadData,3000);\n }\n\n loadData(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n data: data,\n devices: data.devices\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/global/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n newDevice(){\n window.location.href = '/devices/editor/'\n }\n\n render() {\n\n const devices = this.state.devices.map((device) => {\n if(device.type === 'action.devices.types.LIGHT')\n return \n else if(device.type === 'action.devices.types.OUTLET')\n return \n else if(device.type === 'action.devices.types.AC_UNIT')\n return \n else if(device.type === 'action.devices.types.AIRFRESHENER')\n return \n else if(device.type === 'action.devices.types.AIRPURIFIER')\n return \n else if(device.type === 'action.devices.types.BED')\n return \n else if(device.type === 'action.devices.types.FAN')\n return \n else if(device.type === 'action.devices.types.FIREPLACE')\n return \n else if(device.type === 'action.devices.types.RADIATOR')\n return \n else if(device.type === 'action.devices.types.SWITCH')\n return \n else if(device.type === 'action.devices.types.THERMOSTAT')\n return \n else if(device.type === 'action.devices.types.AIRCOOLER')\n return \n else if(device.type === 'action.devices.types.BATHTUB')\n return \n else if(device.type === 'action.devices.types.AWING')\n return \n else if(device.type === 'action.devices.types.AIRCOOLER')\n return \n else if(device.type === 'action.devices.types.BLINDS')\n return \n else if(device.type === 'action.devices.types.CLOSET')\n return \n else if(device.type === 'action.devices.types.CURTAIN')\n return \n else if(device.type === 'action.devices.types.DOOR')\n return \n else if(device.type === 'action.devices.types.DRAWER')\n return \n else if(device.type === 'action.devices.types.GARAGE')\n return \n else if(device.type === 'action.devices.types.GATE')\n return \n else if(device.type === 'action.devices.types.PERGOLA')\n return \n else if(device.type === 'action.devices.types.SHUTTER')\n return \n else if(device.type === 'action.devices.types.VALVE')\n return \n else if(device.type === 'action.devices.types.WINDOW')\n return \n else if(device.type === 'action.devices.types.LOCK')\n return \n else if(device.type === 'action.devices.types.HEATER')\n return \n else if(device.type === 'action.devices.types.HOOD')\n return \n else if(device.type === 'action.devices.types.SECURITYSYSTEM')\n return \n else if(device.type === 'action.devices.types.BLENDER')\n return \n else if(device.type === 'action.devices.types.SCENE')\n return \n else\n return \n });\n\n return (\n \n
\n
Devices and scences \n \n\n
\n { devices }\n
\n\n
\n New \n
\n
\n );\n }\n}\n\nexport default Devices\n","import React from 'react';\n\nimport '../pages/Editor.css';\n\nclass Text extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n }\n\n\n update(event){\n this.props.update(this.props.data,event.target.value);\n }\n\n render() {\n return (\n \n
\n {this.props.name}\n
\n
\n \n
\n
\n );\n }\n}\n\nexport default Text\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Scene extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n \n
\n
\n sceneReversible \n
\n
\n {this.updateCheckbox(checked,\"sceneReversible\")}} checked={this.props.attributes.sceneReversible} />\n
\n
\n Enable it if the scene can be desabled. \n
\n
\n
\n );\n }\n}\n\nexport default Scene\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass OnOff extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n
\n
\n commandOnlyOnOff \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyOnOff\")}} checked={this.props.attributes.commandOnlyOnOff} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state. \n
\n
\n
\n
\n queryOnlyOnOff \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyOnOff\")}} checked={this.props.attributes.queryOnlyOnOff} />\n
\n
\n Enable it if Google shouldn't change the device state. \n
\n
\n
\n );\n }\n}\n\nexport default OnOff\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Brightness extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n \n
\n
\n commandOnlyBrightness \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyBrightness\")}} checked={this.props.commandOnlyBrightness} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the brightness. \n
\n
\n
\n );\n }\n}\n\nexport default Brightness\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass FanSpeed extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateFanSpeeds = this.updateFanSpeeds.bind(this);\n this.addFanSpeed = this.addFanSpeed.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateFanSpeeds(event){\n const id = event.target.id.split('_')\n const speed_id = id[1]\n //Process the attribute and value depending of the attribute\n const speed_attribute = id[0] === 'lang' ? id[0] : 'speed_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableFanSpeeds = this.props.attributes.availableFanSpeeds\n temp_availableFanSpeeds.speeds[speed_id].speed_values[0][speed_attribute] = value\n if (id[0] === 'names') temp_availableFanSpeeds.speeds[speed_id].speed_name = value[0]\n this.props.update('attributes/availableFanSpeeds', temp_availableFanSpeeds);\n }\n\n addFanSpeed(){\n var temp_availableFanSpeeds = this.props.attributes.availableFanSpeeds\n temp_availableFanSpeeds.speeds.push({\n \"speed_name\": \"\",\n \"speed_values\": [\n {\n \"speed_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableFanSpeeds', temp_availableFanSpeeds);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const speeds = this.props.attributes.availableFanSpeeds.speeds.map((speed, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Speed name: \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n reversible \n
\n
\n {this.updateCheckbox(checked,\"reversible\")}} checked={this.props.attributes.reversible} />\n
\n
\n Enable it if the fan supports blowing in both directions. \n
\n
\n\n
\n
\n supportsFanSpeedPercent \n
\n
\n {this.updateCheckbox(checked,\"supportsFanSpeedPercent\")}} checked={this.props.attributes.supportsFanSpeedPercent} />\n
\n
\n Enable it if the speed can be controlled with a number from 0 to 100. \n
\n
\n\n
\n
\n commandOnlyFanSpeed \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyFanSpeed\")}} checked={this.props.attributes.commandOnlyFanSpeed} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the fan speed. \n
\n
\n\n
\n
\n Add a speed\n
\n
\n Add \n
\n
\n\n {speeds}\n\n
\n );\n }\n}\n\nexport default FanSpeed\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass ColorSetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n
\n
\n Color type \n
\n
\n \n Select \n RGB light \n HSV light \n Color temperature \n \n
\n
\n \n
\n
\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum color temperature (in Kelvin) supported by the device. \n
\n
\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum color temperature (in Kelvin) supported by the device. \n
\n
\n
\n
\n commandOnlyColorSetting \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyColorSetting\")}} checked={this.props.attributes.commandOnlyColorSetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the color. \n
\n
\n\n
\n );\n }\n}\n\nexport default ColorSetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass TemperatureSetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_availableThermostatModes = this.props.attributes.availableThermostatModes.split(',')\n\n if (event.target.value === 'delete'){\n temp_availableThermostatModes.splice(mode_id, 1)\n } else if (event.target.value !== 'select') {\n temp_availableThermostatModes[mode_id] = event.target.value;\n }\n\n this.props.update('attributes/availableThermostatModes', temp_availableThermostatModes.join(','));\n }\n\n addMode(){\n var temp_availableThermostatModes = this.props.attributes.availableThermostatModes\n temp_availableThermostatModes += \",\"\n this.props.update('attributes/availableThermostatModes', temp_availableThermostatModes);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n\n render() {\n\n const modes = this.props.attributes.availableThermostatModes.split(',').map((mode, i) => {\n\n return (\n \n
\n
\n
\n
\n \n Mode: \n \n Select a mode \n Delete this mode \n Off \n Heat \n Cool \n On \n Heatcool \n Auto \n Fan only \n Purifier \n Eco \n Dry \n \n \n
\n
\n
\n\n )\n });\n\n return (\n \n\n
\n
\n Add a thermostat mode\n
\n
\n Add \n
\n
\n\n {modes}\n\n
\n
\n commandOnlyTemperatureSetting \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTemperatureSetting\")}} checked={this.props.attributes.commandOnlyTemperatureSetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the temperature. \n
\n
\n\n
\n
\n queryOnlyTemperatureSetting \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyTemperatureSetting\")}} checked={this.props.attributes.queryOnlyTemperatureSetting} />\n
\n
\n Enable it if Google shouldn't change the device temperature settings. \n
\n
\n\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Range\n
\n
\n \n
\n
\n Specifies the minimum offset between heat-cool setpoints in Celsius. \n
\n
\n\n
\n
\n Units\n
\n
\n \n Celsius \n Fahrenheit \n \n
\n
\n\n\n\n
\n );\n }\n}\n\nexport default TemperatureSetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Toggles extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updatetoggle = this.updatetoggle.bind(this);\n this.addToggle = this.addToggle.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updatetoggle(event){\n const id = event.target.id.split('_')\n const toggle_id = id[1]\n //Process the attribute and value depending of the attribute\n const toggle_attribute = id[0] === 'lang' ? id[0] : 'name_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableToggles = this.props.attributes.availableToggles\n temp_availableToggles[toggle_id].name_values[0][toggle_attribute] = value\n if (id[0] === 'names') temp_availableToggles[toggle_id].name = value[0]\n this.props.update('attributes/availableToggles', temp_availableToggles);\n }\n\n addToggle(){\n var temp_availableToggles = this.props.attributes.availableToggles\n temp_availableToggles.push({\n \"name\": \"\",\n \"name_values\": [\n {\n \"name_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableToggles', temp_availableToggles);\n }\n\n render() {\n\n const names_box = {\n marginLeft: '20px',\n width: '150px'\n }\n\n const toggles = this.props.attributes.availableToggles.map((toggle, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Name: \n \n \n\n\n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n commandOnlyToggles \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyToggles\")}} checked={this.props.attributes.commandOnlyToggles} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the states. \n
\n
\n\n
\n
\n Add a toggle\n
\n
\n Add \n
\n
\n\n {toggles}\n\n
\n );\n }\n}\n\nexport default Toggles\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Modes extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_availableModes = this.props.attributes.availableModes\n\n if(id[0] === 'lang'){\n temp_availableModes[mode_id].name_values[0].lang = event.target.value;\n } else if (id[0] === 'names'){\n temp_availableModes[mode_id].name_values[0].name_synonym = event.target.value.split(',');\n temp_availableModes[mode_id].name = event.target.value.split(',')[0]\n } else if (id[0] === 'settings'){\n var values = event.target.value.split(',')\n var settings = []\n for ( var i = 0; i < values.length; i ++){\n settings.push({\n setting_name: values[i],\n setting_values: [{\n setting_synonym: [values[i]],\n lang: this.props.attributes.availableModes[mode_id].name_values[0].lang\n }]\n })\n }\n temp_availableModes[mode_id].settings = settings\n }\n this.props.update('attributes/availableModes', temp_availableModes);\n }\n\n addMode(){\n var temp_availableModes = this.props.attributes.availableModes\n temp_availableModes.push({\n \"name\": \"\",\n \"name_values\": [\n {\n \"name_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ],\n \"settings\": [\n {\n \"setting_name\": \"\",\n \"setting_values\": [{\n \"setting_synonym\": [\"\"],\n \"lang\": \"en\"\n }]\n }\n ]\n });\n this.props.update('attributes/availableModes', temp_availableModes);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const settings_box = {\n width: '230px'\n }\n\n\n const modes = this.props.attributes.availableModes.map((mode, i) => {\n const settings = mode.settings.map((setting,i) => {return setting.setting_name});\n\n return (\n \n\n )\n });\n\n return (\n \n\n
\n
\n commandOnlyModes \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyModes\")}} checked={this.props.attributes.commandOnlyModes} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the modes. \n
\n
\n\n
\n
\n Add a mode\n
\n
\n Add \n
\n
\n\n {modes}\n\n
\n );\n }\n}\n\nexport default Modes\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass HumiditySetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n\n
\n
\n Minimum humidity\n
\n
\n \n
\n
\n Minimum humidity level as percentage. \n
\n
\n\n
\n
\n Maximum humidity\n
\n
\n \n
\n
\n Maximum humidity level as percentage. \n
\n
\n\n
\n
\n commandOnlyHumiditySetting \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyHumiditySetting\")}} checked={this.props.attributes.commandOnlyHumiditySetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the humidity. \n
\n
\n\n
\n
\n queryOnlyHumiditySetting \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyHumiditySetting\")}} checked={this.props.attributes.queryOnlyHumiditySetting} />\n
\n
\n Enable it if Google shouldn't change the device humidity. \n
\n
\n\n
\n );\n }\n}\n\nexport default HumiditySetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass OpenClose extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n
\n
\n discreteOnlyOpenClose \n
\n
\n {this.updateCheckbox(checked,\"discreteOnlyOpenClose\")}} checked={this.props.attributes.discreteOnlyOpenClose} />\n
\n
\n Enable it if the device must either be fully open or fully closed. \n
\n
\n\n
\n
\n commandOnlyOpenClose \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyOpenClose\")}} checked={this.props.attributes.commandOnlyOpenClose} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state. \n
\n
\n\n
\n
\n queryOnlyOpenClose \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyOpenClose\")}} checked={this.props.attributes.queryOnlyOpenClose} />\n
\n
\n Enable it if Google shouldn't change the device state. \n
\n
\n\n
\n );\n }\n}\n\nexport default OpenClose\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Rotation extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n\n
\n
\n Minimum rotation\n
\n
\n \n
\n
\n Minimum rotation degrees that a device can rotate. \n
\n
\n\n
\n
\n Maximum rotation\n
\n
\n \n
\n
\n Maximum rotation degrees that a device can rotate. \n
\n
\n\n
\n
\n commandOnlyRotation \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyRotation\")}} checked={this.props.attributes.commandOnlyRotation} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the device. \n
\n
\n\n
\n
\n supportsContinuousRotation \n
\n
\n {this.updateCheckbox(checked,\"supportsContinuousRotation\")}} checked={this.props.attributes.supportsContinuousRotation} />\n
\n
\n Enable it if the device supports continuous rotation. \n
\n
\n\n
\n
\n supportsDegrees \n
\n
\n {this.updateCheckbox(checked,\"supportsDegrees\")}} checked={this.props.attributes.supportsDegrees} />\n
\n
\n Enable it if the device allows rotation by degree. \n
\n
\n\n
\n
\n supportsPercent \n
\n
\n {this.updateCheckbox(checked,\"supportsPercent\")}} checked={this.props.attributes.supportsPercent} />\n
\n
\n Enable it if device allows rotation by percent. \n
\n
\n\n
\n );\n }\n}\n\nexport default Rotation\n","import React from 'react';\n\nclass Fill extends React.Component {\n constructor(props) {\n super(props);\n this.updateLevels = this.updateLevels.bind(this);\n this.addLevel = this.addLevel.bind(this);\n }\n\n updateLevels(event){\n const id = event.target.id.split('_')\n const level_id = id[1]\n //Process the attribute and value depending of the attribute\n const level_attribute = id[0] === 'lang' ? id[0] : 'level_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableFillLevels = this.props.attributes.availableFillLevels\n temp_availableFillLevels.levels[level_id].level_values[0][level_attribute] = value\n if (id[0] === 'names') temp_availableFillLevels.levels[level_id].level_name = value[0]\n this.props.update('attributes/availableFillLevels', temp_availableFillLevels);\n }\n\n addLevel(){\n var temp_availableFillLevels = this.props.attributes.availableFillLevels\n temp_availableFillLevels.levels.push({\n \"level_name\": \"\",\n \"level_values\": [\n {\n \"level_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableFillLevels', temp_availableFillLevels);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const levels = this.props.attributes.availableFillLevels.levels.map((level, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Fill level name: \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n Add a level\n
\n
\n Add \n
\n
\n\n {levels}\n\n
\n );\n }\n}\n\nexport default Fill\n","import React from 'react';\n\nclass ArmDisarm extends React.Component {\n constructor(props) {\n super(props);\n this.updateSecurityLevel = this.updateSecurityLevel.bind(this);\n this.addSecurityLevel = this.addSecurityLevel.bind(this);\n }\n\n updateSecurityLevel(event){\n const id = event.target.id.split('_')\n const level_id = id[1]\n //Process the attribute and value depending of the attribute\n const level_attribute = id[0] === 'lang' ? id[0] : 'level_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableArmLevels = this.props.attributes.availableArmLevels\n temp_availableArmLevels.levels[level_id].level_values[0][level_attribute] = value\n if (id[0] === 'names') temp_availableArmLevels.levels[level_id].level_name = value[0]\n this.props.update('attributes/availableArmLevels', temp_availableArmLevels);\n }\n\n addSecurityLevel(){\n var temp_availableArmLevels = this.props.attributes.availableArmLevels\n temp_availableArmLevels.levels.push({\n \"level_name\": \"\",\n \"level_values\": [\n {\n \"level_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableArmLevels', temp_availableArmLevels);\n }\n\n render() {\n\n const names_box = {\n marginLeft: '20px',\n width: '150px'\n }\n\n const levels = this.props.attributes.availableArmLevels.levels.map((level, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Level name: \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n Add a security level\n
\n
\n Add \n
\n
\n\n {levels}\n\n
\n );\n }\n}\n\nexport default ArmDisarm\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass StartStop extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateArray = this.updateArray.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateArray(event){\n this.props.update('attributes/' + event.target.id,event.target.value.split(','));\n }\n\n render() {\n return (\n \n
\n
\n pausable \n
\n
\n {this.updateCheckbox(checked,\"pausable\")}} checked={this.props.attributes.pausable} />\n
\n
\n Enable it if the device can be paused. \n
\n
\n\n
\n
\n Zones\n
\n
\n \n
\n
\n\n
\n
\n\n
\n
\n Supported zones names separeted by commas. \n
\n
\n\n\n
\n );\n }\n}\n\nexport default StartStop\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Timer extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.update = this.update.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n render() {\n return (\n \n
\n
\n commandOnlyTimer \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTimer\")}} checked={this.props.attributes.commandOnlyTimer} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state. \n
\n
\n\n
\n
\n Max time\n
\n
\n \n
\n
\n\n
\n
\n\n
\n
\n Indicates the longest timer setting in seconds available on the device. \n
\n
\n
\n );\n }\n}\n\nexport default Timer\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass TemperatureControl extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n \n\n
\n
\n commandOnlyTemperatureControl \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTemperatureControl\")}} checked={this.props.attributes.commandOnlyTemperatureControl} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the temperature. \n
\n
\n\n
\n
\n queryOnlyTemperatureControl \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyTemperatureControl\")}} checked={this.props.attributes.queryOnlyTemperatureControl} />\n
\n
\n Enable it if Google shouldn't change the device temperature settings. \n
\n
\n\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Step\n
\n
\n \n
\n
\n Specifies the relative temperature step. \n
\n
\n\n
\n
\n Units\n
\n
\n \n Celsius \n Fahrenheit \n \n
\n
\n\n\n\n
\n );\n }\n}\n\nexport default TemperatureControl\n","import React from 'react';\n\nclass Cook extends React.Component {\n constructor(props) {\n super(props);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n this.updatePreset = this.updatePreset.bind(this);\n this.addPreset = this.addPreset.bind(this);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_supportedCookingModes = this.props.attributes.supportedCookingModes\n\n if (event.target.value === 'delete'){\n temp_supportedCookingModes.splice(mode_id, 1)\n } else if (event.target.value !== 'select') {\n temp_supportedCookingModes[mode_id] = event.target.value;\n }\n\n this.props.update('attributes/supportedCookingModes', temp_supportedCookingModes);\n }\n\n addMode(){\n var temp_supportedCookingModes = this.props.attributes.supportedCookingModes\n temp_supportedCookingModes.push(\"\");\n this.props.update('attributes/supportedCookingModes', temp_supportedCookingModes);\n }\n\n updatePreset(event){\n const id = event.target.id.split('_')\n const preset_id = id[1]\n var temp_foodPresets = this.props.attributes.foodPresets\n\n if(id[0] === 'lang'){\n temp_foodPresets[preset_id].food_synonyms[0].lang = event.target.value;\n } else if (id[0] === 'names'){\n temp_foodPresets[preset_id].food_synonyms[0].synonym = event.target.value.split(',');\n temp_foodPresets[preset_id].food_preset_name = event.target.value.split(',')[0]\n } else if (id[0] === 'units'){\n temp_foodPresets[preset_id].supported_units[0] = event.target.value;\n }\n this.props.update('attributes/foodPresets', temp_foodPresets);\n }\n\n addPreset(){\n var temp_foodPresets = this.props.attributes.foodPresets\n temp_foodPresets.push({\n \"food_preset_name\": \"\",\n \"supported_units\": [\"\"],\n \"food_synonyms\": [{\n \"synonym\": [\"\"],\n \"language\": \"en\"\n }]\n });\n this.props.update('attributes/foodPresets', temp_foodPresets);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const modes = this.props.attributes.supportedCookingModes.map((mode, i) => {\n\n return (\n \n
\n
\n
\n
\n \n Mode: \n \n Select a mode \n Delete this mode \n UNKNOWN_COOKING_MODE \n BAKE \n BEAT \n BLEND \n BOIL \n BREW \n BROIL \n CONVECTION_BAKE \n COOK \n DEFROST \n DEHYDRATE \n FERMENT \n FRY \n KNEAD \n MICROWAVE \n PRESSURE_COOK \n PUREE \n ROAST \n SAUTE \n SLOW_COOK \n SOUS_VIDE \n STEAM \n STEW \n WARM \n WHIP \n \n \n
\n
\n
\n\n )\n });\n\n const presets = this.props.attributes.foodPresets.map((preset, i) => {\n\n return (\n \n
\n
\n
\n
\n \n Language: \n \n es \n en \n \n \n \n Preset name: \n \n \n \n Units: \n \n No units \n Unkown \n Centimeters \n Cups \n Deciliters \n Feet \n Fluid ounces \n Gallons \n Grams \n Inches \n Kilograms \n Liters \n Meters \n Miligrams \n Mililiters \n Milimeters \n Ounces \n Pinch \n Pints \n Portion \n Pounds \n Quarts \n Tablespoons \n Teaspoons \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n Add a cooking mode\n
\n
\n Add \n
\n
\n\n {modes}\n\n
\n
\n Add a preset\n
\n
\n Add \n
\n
\n\n {presets}\n\n
\n );\n }\n}\n\nexport default Cook\n","import React from 'react';\n\nclass SensorState extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n }\n\n update(event){\n const value = event.target.value;\n var sensor = {\n name: value\n }\n\n switch (value) {\n default:\n sensor['descriptiveCapabilities'] = {\n availableStates: ['fair','good','healthy','moderate','poor','severe','unhealthy','unhealthy for sensitive groups','very poor','very unhealthy','unknown'],\n }\n sensor['numericCapabilities']= { rawValueUnit: \"AQI\" }\n break;\n case 'AirQuality':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['fair','good','healthy','moderate','poor','severe','unhealthy','unhealthy for sensitive groups','very poor','very unhealthy','unknown'],\n }\n sensor['numericCapabilities']= { rawValueUnit: \"AQI\" }\n break;\n case 'CarbonDioxideLevel':\n sensor['descriptiveCapabilities'] = {\n numericCapabilities: { rawValueUnit: \"PARTS_PER_MILLION\" }\n }\n break;\n case 'CarbonMonoxideLevel':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['carbon monoxide detected','high','no carbon monoxide detected','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n case 'FilterCleanliness':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['clean','dirty','needs replacement','unknown']\n }\n break;\n case 'FilterLifeTime':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['good','new','replace soon','replace now','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'HEPAFilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'Max2FilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'PM2.5':\n sensor['numericCapabilities']= { rawValueUnit: \"MICROGRAMS_PER_CUBIC_METER\" }\n break;\n case 'PM10':\n sensor['numericCapabilities']= { rawValueUnit: \"MICROGRAMS_PER_CUBIC_METER\" }\n break;\n case 'PreFilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'SmokeLevel':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['smoke detected','high','no smoke detected','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n case 'WaterLeak':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['leak','no leak','unknown']\n }\n break;\n case 'RainDetection':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['rain detected','no rain detected','unknown']\n }\n break;\n case 'VolatileOrganicCompounds':\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n }\n\n var sensorStatesSupported = []\n sensorStatesSupported.push(sensor);\n this.props.update('attributes/' + event.target.id,sensorStatesSupported);\n }\n\n render() {\n return (\n \n
\n
\n Sensor type\n
\n
\n \n Select \n Air Quality \n Carbon Dioxide Level \n Carbon Monoxide Level \n Filter Clean liness \n Filter Life Time \n HEPA Filter Life Time \n Max2 Filter Life Time \n PM2.5 \n PM10 \n PreFilter Life Time \n Smoke Level \n Water Leak \n Rain Detection \n Volatile Organic Compounds \n \n
\n
\n \n
\n
\n\n
\n );\n }\n}\n\nexport default SensorState\n","import React from 'react';\nimport Switch from \"react-switch\";\nimport Text from '../editor/Text'\nimport Scene from '../editor/traits/Scene'\nimport OnOff from '../editor/traits/OnOff'\nimport Brightness from '../editor/traits/Brightness'\nimport FanSpeed from '../editor/traits/FanSpeed'\nimport ColorSetting from '../editor/traits/ColorSetting'\nimport TemperatureSetting from '../editor/traits/TemperatureSetting'\nimport Toggles from '../editor/traits/Toggles'\nimport Modes from '../editor/traits/Modes'\nimport HumiditySetting from '../editor/traits/HumiditySetting'\nimport OpenClose from '../editor/traits/OpenClose'\nimport Rotation from '../editor/traits/Rotation'\nimport Fill from '../editor/traits/Fill'\nimport ArmDisarm from '../editor/traits/ArmDisarm'\nimport StartStop from '../editor/traits/StartStop'\nimport Timer from '../editor/traits/Timer'\nimport TemperatureControl from '../editor/traits/TemperatureControl'\nimport Cook from '../editor/traits/Cook'\nimport SensorState from '../editor/traits/SensorState'\nimport getCookieValue from '../../functions'\nimport { root, deviceReference } from '../../constants'\n\nimport './Editor.css';\n\nclass Editor extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n var create = false;\n if (id === \"\") create = true;\n this.state = {\n id: id,\n create: create,\n device: {\n attributes: {},\n deviceInfo: {},\n id: \"\",\n name: {\n defaultNames: [],\n nicknames: [],\n name: \"\"\n },\n traits: [],\n type: \"\"\n },\n status: {\n online: true\n },\n posible_traits: [],\n save_status: \"\"\n }\n this.updateNames = this.updateNames.bind(this);\n this.update = this.update.bind(this);\n this.updateId = this.updateId.bind(this);\n this.updateType = this.updateType.bind(this);\n this.updateTraits = this.updateTraits.bind(this);\n this.save = this.save.bind(this);\n this.delete = this.delete.bind(this);\n this.renderAttrinutes = this.renderAttrinutes.bind(this);\n }\n\n componentDidMount() {\n if (!this.state.create){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n device: data,\n posible_traits: deviceReference.devices[data.type].traits\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n }\n\n updateNames(dumy_key, value){\n var names = value.split(',');\n var temp_device = this.state.device\n temp_device.name = {\n defaultNames: names,\n nicknames: names,\n name: names[0]\n }\n this.setState({\n device: temp_device\n })\n }\n\n update(key, value){\n var temp_device = this.state.device\n var keys = key.split('/');\n if (keys.length === 1)\n temp_device[key] = value\n else if (keys.length === 2)\n temp_device[keys[0]][keys[1]] = value\n else if (keys.length === 3)\n temp_device[keys[0]][keys[1]][keys[2]] = value\n this.setState({\n device: temp_device\n })\n }\n\n updateId(event){\n this.update('id',event.target.value)\n }\n\n updateType(event){\n this.update('type',event.target.value)\n this.setState({\n posible_traits: deviceReference.devices[event.target.value].traits\n });\n }\n\n updateTraits(checked, trait){\n var temp_device = this.state.device\n var temp_status = this.state.status\n if (checked) {\n if (this.state.device.traits.includes(trait) === false){\n //Push the trait to the device\n temp_device.traits.push(trait)\n //Set the default values\n var attributes = deviceReference.traits[trait].attributes;\n Object.keys(attributes).forEach((attribute, i) => {\n temp_device.attributes[attribute] = attributes[attribute].default\n });\n //Set the default status params\n var params = deviceReference.traits[trait].params;\n params.forEach((param, i) => {\n temp_status[param] = deviceReference.params[param].default\n });\n }\n } else {\n if (this.state.device.traits.includes(trait) === true){\n temp_device.traits = temp_device.traits.filter(function(value, index, arr){ return value !== trait;});\n }\n }\n this.setState({\n device: temp_device,\n status: temp_status\n })\n }\n\n save(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n JSON.parse(http.responseText);\n this.setState({\n save_status: \"Saved correctly.\"\n });\n if (this.state.create) {\n window.location.href = '/devices'\n }\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the changes haven't been saved.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n var payload = {\n \"device\": this.state.device\n }\n if (this.state.create){\n http.open(\"POST\", root + \"api/devices/create/\");\n payload.status = this.state.status\n } else {\n http.open(\"POST\", root + \"api/devices/update/\");\n }\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify(payload));\n }\n\n delete(){\n if(window.confirm('Do you want to delete the device?')){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n window.location.href = \"/devices/\"\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the device hasn't been deleted.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/devices/delete/\" + this.state.device.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n } else {\n this.setState({\n save_status: \"Ok. The device is save.\"\n });\n }\n }\n\n renderAttrinutes(trait){\n if (this.state.device.traits.includes(trait)){\n if (trait === 'action.devices.traits.Scene')\n return \n else if (trait === 'action.devices.traits.OnOff')\n return \n else if (trait === 'action.devices.traits.Brightness')\n return \n else if (trait === 'action.devices.traits.ColorSetting')\n return \n else if (trait === 'action.devices.traits.FanSpeed')\n return \n else if (trait === 'action.devices.traits.TemperatureSetting')\n return \n else if (trait === 'action.devices.traits.Toggles')\n return \n else if (trait === 'action.devices.traits.Modes')\n return \n else if (trait === 'action.devices.traits.HumiditySetting')\n return \n else if (trait === 'action.devices.traits.OpenClose')\n return \n else if (trait === 'action.devices.traits.Rotation')\n return \n else if (trait === 'action.devices.traits.Fill')\n return \n else if (trait === 'action.devices.traits.ArmDisarm')\n return \n else if (trait === 'action.devices.traits.StartStop')\n return \n else if (trait === 'action.devices.traits.Timer')\n return \n else if (trait === 'action.devices.traits.TemperatureControl')\n return \n else if (trait === 'action.devices.traits.Cook')\n return \n else if (trait === 'action.devices.traits.SensorState')\n return \n }\n }\n\n render() {\n\n const deleteButton = {\n backgroundColor: 'red'\n }\n\n const deleteButtonDisabled = {\n backgroundColor: 'red',\n opacity: '0.2'\n }\n\n const types = Object.keys(deviceReference.devices).map((type) => {\n return {deviceReference.devices[type].name} \n })\n\n const nicknames = this.state.device.name.nicknames.map((name) => {\n return name\n });\n\n const traits = this.state.posible_traits.map((trait) =>\n \n
\n
\n
\n {deviceReference.traits[trait].name} \n
\n
\n {this.updateTraits(checked,trait)}} checked={this.state.device.traits.includes(trait)} />\n
\n
\n
\n {this.renderAttrinutes(trait)}\n
\n );\n\n return (\n \n\n
\n
Global settings \n
\n General settings of the device. \n
\n \n
\n
\n
\n Device ID*\n
\n
\n \n
\n
\n
\n
\n Device Type*\n
\n
\n \n Select a device \n {types}\n \n
\n
\n
\n \n \n \n \n \n Nick names must be separeted by , commas. \n * data is required. \n
\n \n Traits \n \n The traits define what the device can do. \n
\n {traits}\n \n \n Delete \n Save \n {this.state.save_status} \n
\n \n
\n\n
\n );\n }\n}\n\nexport default Editor\n","import React from 'react';\nimport ReactJson from 'react-json-view'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Editor extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n this.state = {\n id: id,\n device: {\n attributes: {},\n deviceInfo: {},\n id: \"\",\n name: {\n defaultnames: [],\n nicknames: [],\n name: \"\"\n },\n traits: [],\n type: \"\"\n },\n status: {\n online: true\n }\n }\n }\n\n componentDidMount() {\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n var data = JSON.parse(dev.responseText);\n this.setState({\n device: data\n });\n } else {\n console.error(dev.statusText);\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n\n var sta = new XMLHttpRequest();\n sta.onload = function (e) {\n if (sta.readyState === 4) {\n if (sta.status === 200) {\n var data = JSON.parse(sta.responseText);\n this.setState({\n status: data\n });\n } else {\n console.error(sta.statusText);\n }\n }\n }.bind(this);\n sta.open(\"GET\", root + \"api/status/get/\" + this.state.id + \"/\");\n sta.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n sta.send();\n }\n\n\n\n render() {\n\n const json_viewer = {\n textAlign: 'left',\n }\n\n return (\n \n\n
\n
Device definition \n
\n General settings of the device. \n
\n \n
\n \n
\n
\n\n
\n
Device status \n
\n Status of the device. \n
\n \n
\n \n
\n
\n\n
\n );\n }\n}\n\nexport default Editor\n","import React from 'react';\nimport ReactJson from 'react-json-view'\nimport getCookieValue from '../../functions'\nimport { root, deviceReference } from '../../constants'\n\nimport './Connecting.css';\n\nclass Connecting extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3]\n this.state = {\n id: id,\n traits: [],\n params: [],\n commands: []\n }\n }\n\n componentDidMount() {\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n const data = JSON.parse(dev.responseText);\n const traits = data.traits;\n var commands = [];\n var params = []\n traits.forEach((trait) => {\n params = params.concat(deviceReference.traits[trait].params);\n commands = commands.concat(deviceReference.traits[trait].commands);\n });\n this.setState({\n traits: traits,\n params: params,\n commands: commands\n });\n } else {\n console.error(dev.statusText)\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n }\n\n render() {\n\n const params = this.state.params.map((param, i) => {\n var type = deviceReference.params[param].type\n if (type === 'list')\n type = 'string'\n\n var topic = 'None - Controlled only by the device'\n if (deviceReference.params[param].commanded)\n topic = 'device/' + this.state.id + '/' + param\n\n return (\n \n
{param}
\n
{topic}
\n
{type}
\n
\n )\n })\n\n const commands = this.state.commands.map((command, i) => {\n return (\n \n
{command.command}
\n
{'device/' + this.state.id + '/command'}
\n
{command.description}
\n
\n )\n })\n\n var example = {\"id\":\"light001\",\"param\":\"brightness\",\"value\":\"80\",\"intent\":\"execute\"}\n var advise = {\n textAlign: 'left'\n }\n\n return (\n \n\n
\n
Params \n
\n
Params are data interchanged between Google and the device and stored in Homeware database.
\n
If the param has got a notification topic, Google Home can control it. A notification will be sent in this MQTT topic when Google change a param.
\n
If the param hasn't got a notification topic, the device should update the param value when necessary.
\n
\n
\n
\n
Param
\n
Notifications topic
\n
Type
\n
\n {params}\n
\n
\n
The device can change the value of any param sending an execute request to device/control topic as follow
\n
\n \n
\n\n
\n
Commands \n
\n
Commands are directs orders from Google to the device. Commands are not stored in Homeware's database.
\n
\n
\n
\n
Command
\n
Notifications topic
\n
Description
\n
\n {commands}\n
\n\n
\n );\n }\n}\n\nexport default Connecting\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Tasks.css';\n\nclass Tasks extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n devices: [],\n tasks: []\n }\n this.loadData = this.loadData.bind(this);\n this.openManager = this.openManager.bind(this);\n this.newTask = this.newTask.bind(this);\n }\n\n componentDidMount() {\n this.loadData();\n }\n\n loadData(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n devices: data.devices,\n tasks: data.tasks\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/global/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n openManager(event){\n window.location.href = '/tasks/manager/' + event.target.id.split('_')[1]\n }\n\n newTask(){\n window.location.href = '/tasks/manager/'\n }\n\n render() {\n\n const tasks = this.state.tasks.map((task, i) => {\n return(\n \n
{ task.title } \n
\n
{ task.description }
\n
\n )\n });\n\n return (\n \n
\n
Tasks \n \n\n
\n {tasks}\n
\n\n
\n New \n
\n
\n );\n }\n}\n\nexport default Tasks\n","import React from 'react';\nimport Triggers from './Triggers'\n\nimport '../pages/Manager.css';\n\nclass Logic extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n this.addOr = this.addOr.bind(this);\n this.addAnd = this.addAnd.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n addOr() {\n this.props.addTriggerLogic('or',this.props.id)\n }\n\n addAnd() {\n this.props.addTriggerLogic('and',this.props.id)\n }\n\n openTriggerAssistant() {\n this.props.openTriggerAssistant(this.props.id)\n }\n\n render() {\n\n const num_operations = this.props.triggers[this.props.id].operation.length-1;\n const operations = this.props.triggers[this.props.id].operation.map((op, i) => {\n return (\n \n \n {i < num_operations ? {this.props.triggers[this.props.id].type} : '' }\n
\n );\n });\n\n return (\n \n {operations}\n
\n Or \n And \n Trigger \n Delete \n
\n
\n );\n }\n}\n\nexport default Logic\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Trigger extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n this.renderTriggerText = this.renderTriggerText.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n renderTriggerText() {\n const week = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']\n const device_triggers = ['d2b','d2i','d2l','d2s']\n\n const type = this.props.triggers[this.props.id].type;\n const operation = this.props.triggers[this.props.id].operation.split(':');\n if (device_triggers.includes(type)) {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + operation[3];\n } else if (type === 'd2d') {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + this.props.devices[operation[3]] + ' (' + (deviceReference.params[operation[4]].name ? deviceReference.params[operation[4]].name : operation[4]) + ') ';\n } else if (type === 'd2c') {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + operation[3];\n } else if (type === 'time') {\n\n var days = '';\n for( var i = 0; i < operation[2].length; i++){\n days += week[operation[2][i]];\n if (i !== operation[2].length - 1)\n days += ', ';\n }\n return operation[0] + ':' + operation[1] + ' on ' + days\n\n } else {\n return this.props.triggers[this.props.id].operation\n }\n }\n\n render() {\n\n return (\n \n
{this.renderTriggerText()} \n
\n
\n );\n }\n}\n\nexport default Trigger\n","import React from 'react';\nimport Logic from './Logic'\nimport Trigger from './Trigger'\n\nclass Triggers extends React.Component {\n constructor(props) {\n super(props);\n this.addOr = this.addOr.bind(this);\n this.addAnd = this.addAnd.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n }\n\n addOr() {\n this.props.addTriggerLogic('or','triggers')\n }\n\n addAnd() {\n this.props.addTriggerLogic('and','triggers')\n }\n\n openTriggerAssistant() {\n this.props.openTriggerAssistant('triggers')\n }\n\n render() {\n\n if (this.props.triggers.trigger) {\n var operation = this.props.triggers[this.props.id]\n const device_triggers = ['d2b','d2d','d2i','d2l','time','d2c']\n\n if (operation.type === 'or'){\n return \n } else if (operation.type === 'and'){\n return \n } else if (device_triggers.includes(operation.type)){\n return \n }\n } else {\n return (\n \n Or \n And \n Trigger \n
\n );\n }\n\n }\n}\n\nexport default Triggers\n","import React from 'react';\n\nimport '../pages/Manager.css';\n\nclass Assistant extends React.Component {\n constructor(props) {\n super(props);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n }\n\n addTriggerOperation(){\n const hour = document.getElementById('hour').value;\n const minute = document.getElementById('minute').value;\n var week = '';\n\n if (document.getElementById('monday').checked)\n week += '1'\n if (document.getElementById('tuesday').checked)\n week += '2'\n if (document.getElementById('wednesday').checked)\n week += '3'\n if (document.getElementById('thursday').checked)\n week += '4'\n if (document.getElementById('friday').checked)\n week += '5'\n if (document.getElementById('saturday').checked)\n week += '6'\n if (document.getElementById('sunday').checked)\n week += '0'\n\n const value = hour + ':' + minute + ':' + week;\n this.props.addTriggerOperation('time',value);\n this.props.closeTriggerAssistant();\n }\n\n render() {\n\n return (\n \n
Triggered by time \n
\n
\n Hour*\n
\n
\n \n
\n
\n 24h format \n
\n
\n
\n
\n Minute*\n
\n
\n \n
\n
\n \n
\n
\n\n
\n
\n Week*\n
\n
\n Sunday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Monday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Tuesday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Wednesday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Thursday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Friday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Saturday\n
\n
\n \n
\n
\n\n\n\n\n\n
\n Save \n Cancel \n
\n
\n );\n }\n}\n\nexport default Assistant\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Device extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device: \"\"\n }\n this.updateDevice = this.updateDevice.bind(this);\n this.updateParam = this.updateParam.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n this.typeConversion = this.typeConversion.bind(this);\n }\n\n updateDevice(event) {\n this.setState({\n device: event.target.value\n });\n }\n\n updateParam(event) {\n this.setState({\n param: event.target.value\n });\n }\n\n addTriggerOperation(){\n const device = document.getElementById('device').value;\n const param = document.getElementById('param').value;\n const comparator = document.getElementById('comparator').value;\n const value = document.getElementById('value').value;\n\n\n const operation = device + ':' + param + ':' + comparator + ':' + value;\n this.props.addTriggerOperation(this.typeConversion(deviceReference.params[this.state.param].type),operation);\n this.props.closeTriggerAssistant();\n }\n\n typeConversion(origen) {\n const type = {\n int: 'd2i',\n list: 'd2l',\n bool: 'd2b',\n string: 'd2s',\n color: 'd2c'\n }\n return type[origen]\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return {this.props.devices[device]} \n })\n\n const params = this.state.device === \"\" ? '' : Object.keys(this.props.status[this.state.device]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n var value = '';\n if (deviceReference.params[this.state.param]){\n const type = this.typeConversion(deviceReference.params[this.state.param].type);\n if(type === 'd2i'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2s'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2b' || type === 'd2l'){\n\n const options = deviceReference.params[this.state.param].select.map((option) => {\n return {option} \n })\n\n value = (\n \n
\n Value*\n
\n
\n \n {options}\n \n
\n
\n )\n }\n\n }\n\n return (\n \n
Triggered by a device \n\n
\n
\n Device*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param*\n
\n
\n \n Select a param \n {params}\n \n
\n
\n
\n
\n Comparator*\n
\n
\n \n = \n < \n > \n <= \n >= \n \n
\n
\n\n {value}\n\n
\n Save \n Cancel \n
\n
\n );\n }\n}\n\nexport default Device\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass DeviceToDevice extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device_a: \"\",\n device_b: \"\"\n }\n this.updateDependencies = this.updateDependencies.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n }\n\n updateDependencies(event) {\n var state = this.state;\n state[event.target.id] = event.target.value;\n this.setState(state);\n }\n\n\n addTriggerOperation(){\n const device_a = document.getElementById('device_a').value;\n const param_a = document.getElementById('param_a').value;\n const comparator = document.getElementById('comparator').value;\n const device_b = document.getElementById('device_b').value;\n const param_b = document.getElementById('param_b').value;\n\n const operation = device_a + ':' + param_a + ':' + comparator + ':' + device_b + ':' + param_b;\n this.props.addTriggerOperation('d2d',operation);\n this.props.closeTriggerAssistant();\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return {this.props.devices[device]} \n })\n\n const params_a = this.state.device_a === \"\" ? '' : Object.keys(this.props.status[this.state.device_a]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n const params_b = this.state.device_b === \"\" ? '' : Object.keys(this.props.status[this.state.device_b]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n return (\n \n
Compare two devices \n\n
\n
\n Device A*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param A*\n
\n
\n \n Select a param \n {params_a}\n \n
\n
\n\n
\n
\n Comparator*\n
\n
\n \n = \n < \n > \n <= \n >= \n \n
\n
\n\n
\n
\n Device B*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param B*\n
\n
\n \n Select a param \n {params_b}\n \n
\n
\n\n
\n Save \n Cancel \n
\n
\n );\n }\n}\n\nexport default DeviceToDevice\n","import React from 'react';\nimport Time from './Time'\nimport Device from './Device'\nimport DeviceToDevice from './DeviceToDevice'\n\nimport '../pages/Manager.css';\n\nclass Assistant extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n type: ''\n }\n this.timeTigger = this.timeTigger.bind(this);\n this.deiceTrigger = this.deiceTrigger.bind(this);\n this.deviceToDeviceTrigger = this.deviceToDeviceTrigger.bind(this);\n }\n\n timeTigger() {\n this.setState({\n type: 'time'\n });\n }\n\n deiceTrigger() {\n this.setState({\n type: 'device'\n });\n }\n\n deviceToDeviceTrigger() {\n this.setState({\n type: 'device2device'\n });\n }\n\n render() {\n\n if (this.state.type === '')\n return (\n \n
Add a new trigger \n
\n Time \n Device \n Device to device \n Cancel \n
\n
\n );\n else if (this.state.type === 'time')\n return \n else if (this.state.type === 'device')\n return \n else if (this.state.type === 'device2device')\n return \n }\n}\n\nexport default Assistant\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Target extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n render() {\n\n const container = {\n marginBottom: '10px'\n }\n\n return (\n \n
{ (this.props.devices[this.props.target.device] ? this.props.devices[this.props.target.device] : this.props.target.device)\n + ' (' + (deviceReference.params[this.props.target.param] ? deviceReference.params[this.props.target.param].name : this.props.target.param)\n + ') = ' + this.props.target.value} \n
\n
\n );\n }\n}\n\nexport default Target\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Device extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device: \"\"\n }\n this.updateDevice = this.updateDevice.bind(this);\n this.updateParam = this.updateParam.bind(this);\n this.addTarget = this.addTarget.bind(this);\n this.typeConversion = this.typeConversion.bind(this);\n }\n\n updateDevice(event) {\n this.setState({\n device: event.target.value\n });\n }\n\n updateParam(event) {\n this.setState({\n param: event.target.value\n });\n }\n\n addTarget(){\n const device = document.getElementById('device').value;\n const param = document.getElementById('param').value;\n const value = document.getElementById('value').value;\n\n const target = {\n device: device,\n param: param,\n value: value\n }\n this.props.addTarget(target);\n document.getElementById('device').value = '';\n document.getElementById('param').value = '';\n this.setState({\n param: ''\n });\n }\n\n typeConversion(origen) {\n const type = {\n int: 'd2i',\n list: 'd2l',\n bool: 'd2b',\n string: 'd2s',\n color: 'd2c'\n }\n return type[origen]\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return {this.props.devices[device]} \n })\n\n const params = this.state.device === \"\" ? '' : Object.keys(this.props.status[this.state.device]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n var value = '';\n if (deviceReference.params[this.state.param]){\n const type = this.typeConversion(deviceReference.params[this.state.param].type);\n if(type === 'd2i'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2s'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2b' || type === 'd2l'){\n\n const options = deviceReference.params[this.state.param].select.map((option) => {\n return {option} \n })\n\n value = (\n \n
\n Value*\n
\n
\n \n {options}\n \n
\n
\n )\n }\n\n }\n\n return (\n \n
New target \n\n
\n
\n Device*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param*\n
\n
\n \n Select a param \n {params}\n \n
\n
\n\n {value}\n\n
\n Add \n
\n
\n );\n }\n}\n\nexport default Device\n","import React from 'react';\nimport Triggers from '../manager/Triggers.js'\nimport Assistant from '../manager/Assistant.js'\nimport Target from '../manager/Target.js'\nimport DeviceTarget from '../manager/DeviceTarget.js'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Manager.css';\n\nclass Manager extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n var create = false;\n if (id === \"\") create = true;\n this.state = {\n id: id,\n create: create,\n save_status: \"\",\n trigger_assistant_parent: 0,\n task: {\n title: '',\n description: '',\n triggers: {},\n target: []\n },\n devices: [],\n status: {}\n }\n this.update = this.update.bind(this);\n this.save = this.save.bind(this);\n this.delete = this.delete.bind(this);\n this.deleteTrigger = this.deleteTrigger.bind(this);\n this.addTriggerLogic = this.addTriggerLogic.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n this.closeTriggerAssistant = this.closeTriggerAssistant.bind(this);\n this.addTarget = this.addTarget.bind(this);\n }\n\n componentDidMount() {\n // Load devices data\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n var data = JSON.parse(dev.responseText);\n var devices_names = {}\n data.devices.forEach((device) => {\n devices_names[device.id] = device.name.name\n })\n this.setState({\n devices: devices_names,\n status: data.status\n });\n } else {\n console.error(dev.statusText);\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/global/get/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n\n // Load task if neeeded\n if (!this.state.create){\n var tas = new XMLHttpRequest();\n tas.onload = function (e) {\n if (tas.readyState === 4) {\n if (tas.status === 200) {\n var data = JSON.parse(tas.responseText);\n console.log(data);\n this.setState({\n task: data\n });\n } else {\n console.error(tas.statusText);\n }\n }\n }.bind(this);\n tas.open(\"GET\", root + \"api/tasks/get/\" + this.state.id + \"/\");\n tas.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n tas.send();\n }\n }\n\n update(event){\n var task = this.state.task;\n task[event.target.id] = event.target.value\n this.setState({\n task: task\n })\n }\n\n save(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n JSON.parse(http.responseText);\n if (this.state.create){\n window.location.href = \"/tasks\"\n } else {\n this.setState({\n save_status: \"Saved correctly.\"\n });\n }\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the changes haven't been saved.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n var payload = {\n \"task\": this.state.task\n }\n if (this.state.create){\n http.open(\"POST\", root + \"api/tasks/create/\");\n } else {\n http.open(\"POST\", root + \"api/tasks/update/\");\n payload['id'] = this.state.id;\n }\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify(payload));\n }\n\n delete(){\n if(window.confirm('Do you want to delete the task?')){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n window.location.href = \"/tasks/\"\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the device hasn't been deleted.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/tasks/delete/\" + this.state.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n } else {\n this.setState({\n save_status: \"Ok. The device is save.\"\n });\n }\n }\n\n deleteTrigger(id) {\n // Get the task\n var task = this.state.task;\n var triggers = task.triggers;\n // Get the the parent id\n const parent = triggers[id].parent\n if (parent !== 'triggers') {\n // Delete from the parent\n const index = triggers[parent].operation.indexOf(id);\n triggers[parent].operation.splice(index,1)\n // Delete the trigger\n delete triggers[id];\n task.triggers = triggers;\n } else {\n task.triggers = {};\n }\n this.setState({\n task: task\n });\n }\n\n addTriggerLogic(type, parent) {\n // Get the triggers\n var task = this.state.task;\n if (parent !== 'triggers') {\n // Get the timestamp\n const ts = Date.now();\n // Compose and create the logic trigger\n task.triggers[ts] = {\n operation: [],\n parent: parent,\n type: type\n };\n // Register the trigger in the parent\n task.triggers[parent].operation.push(ts);\n } else {\n task.triggers['trigger'] = {\n operation: [],\n parent: 'triggers',\n type: type\n };\n }\n // Update the component state\n this.setState({\n task: task\n });\n }\n\n openTriggerAssistant(parent) {\n this.setState({\n trigger_assistant_parent: parent\n });\n }\n\n addTriggerOperation(type, operation) {\n // Get the triggers\n var task = this.state.task;\n const parent = this.state.trigger_assistant_parent;\n if (parent !== 'triggers') {\n // Get the timestamp\n const ts = Date.now();\n // Compose and create the logic trigger\n task.triggers[ts] = {\n operation: operation,\n parent: parent,\n type: type\n };\n // Register the trigger in the parent\n task.triggers[parent].operation.push(ts);\n } else {\n task.triggers['trigger'] = {\n operation: operation,\n parent: 'triggers',\n type: type\n };\n }\n // Update the component state\n this.setState({\n task: task\n });\n }\n\n closeTriggerAssistant() {\n this.setState({\n trigger_assistant_parent: 0\n });\n }\n\n addTarget(target) {\n var task = this.state.task;\n task.target.push(target);\n this.setState({\n task: task\n });\n }\n\n render() {\n\n const button = {\n width: '200px'\n }\n\n const deleteButton = {\n backgroundColor: 'red'\n }\n\n const deleteButtonDisabled = {\n backgroundColor: 'red',\n opacity: '0.2'\n }\n\n const separator = {\n width: '70%'\n }\n\n const targets = this.state.task.target.map((target, i) => {\n return \n })\n\n return (\n \n
Task \n
\n
\n
\n
\n Name*\n
\n
\n \n
\n
\n
\n
\n Description*\n
\n
\n \n
\n
\n
\n
Triggers \n
\n \n
\n {\n this.state.trigger_assistant_parent !== 0\n ?\n
\n :\n \n }\n \n Targets \n \n \n
\n {targets}\n \n\n \n \n Delete \n Save \n {this.state.save_status} \n
\n \n
\n );\n }\n}\n\nexport default Manager\n","import React from 'react';\nimport Switch from \"react-switch\";\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Settings extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n settings: {\n google: {},\n ddns: {},\n mqtt: {},\n apikey: \"\"\n },\n save_status: \"\",\n url: {\n auth: \"\",\n token: \"\",\n fulfillment: \"\"\n }\n }\n this.update = this.update.bind(this);\n this.enableDdnsProvider = this.enableDdnsProvider.bind(this);\n this.save = this.save.bind(this);\n }\n\n componentDidMount() {\n if (!this.state.create){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n settings: data,\n url: {\n auth: \"https://\" + data.ddns.hostname + \"/auth/\",\n token: \"https://\" + data.ddns.hostname + \"/token/\",\n fulfillment: \"https://\" + data.ddns.hostname + \"/smarthome/\"\n }\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/settings/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n }\n\n update(event){\n // this.props.update('attributes/' + event.target.id,event.target.value);\n const id = event.target.id.split(\"/\");\n var settings = this.state.settings;\n if (id.length === 1){\n settings[id[0]] = event.target.value;\n } else if (id.length === 2){\n settings[id[0]][id[1]] = event.target.value;\n }\n this.setState({\n settings: settings\n });\n }\n\n enableDdnsProvider(checked){\n var settings = this.state.settings;\n settings.ddns.enabled = checked;\n this.setState({\n settings: settings\n });\n }\n\n save(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n JSON.parse(http.responseText);\n this.setState({\n save_status: \"Saved correctly.\"\n });\n } else {\n this.setState({\n save_status: \"Error, the changes haven't been saved.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"POST\", root + \"api/settings/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify(this.state.settings));\n }\n\n render() {\n\n return (\n \n
\n
Actions on Google \n
\n
\n
\n
\n Client ID\n
\n
\n \n
\n
\n
\n
\n Client Secret\n
\n
\n \n
\n
\n
\n
\n Authorization URL\n
\n
\n \n
\n
\n
\n
\n Token URL\n
\n
\n \n
\n
\n
\n
\n Fulfillment URL\n
\n
\n \n
\n
\n
\n
\n Save \n {this.state.save_status} \n
\n
\n Actions on Google settings. It is used to authenticate with Google. If you change it here, you must change it on the Actions Console > Develop > Account Linking. \n
\n
\n\n\n
\n
MQTT \n
\n
\n
\n
\n
\n Password\n
\n
\n \n
\n
\n
\n
\n Save \n {this.state.save_status} \n
\n
\n Important. You must configure the username and password into Mosquitto manually from a terminal. This is only for telling Homeware its credentials. Clear both if you don't use credentials. \n
\n
\n\n
\n
DDNS provider \n
\n
\n
\n
\n Status:\n
\n
\n { this.state.settings.ddns.status }\n
\n
\n
\n
\n IP and time:\n
\n
\n { this.state.settings.ddns.ip + \" updated at \" + this.state.settings.ddns.last}\n
\n
\n
\n
\n
\n
\n
\n Enable\n
\n
\n \n
\n
\n
\n
\n Provider\n
\n
\n \n Noip \n \n
\n
\n
\n
\n Username\n
\n
\n \n
\n
\n
\n
\n Password\n
\n
\n \n
\n
\n
\n
\n Hostname\n
\n
\n \n
\n
\n
\n
\n Save \n {this.state.save_status} \n
\n
\n Set up the access data to the DDNS provider account. Open an issue on Github if you want a DDNS provider that is not listed. \n
\n
\n\n\n
\n );\n }\n}\n\nexport default Settings\n","import React from 'react';\n\nfunction Component(props) {\n\n const component = {\n marginTop: '5px',\n width: '100%',\n display: 'grid',\n gridTemplateColumns: '70% 30%'\n }\n\n const textContainer = {\n textAlign: 'left',\n paddingTop: '4px'\n }\n\n const labelContainer = {\n textAlign: 'right',\n paddingTop: '4px'\n }\n\n const text = {\n fontSize: '18px'\n }\n\n const running = {\n fontSize: '12px',\n fontWeight: 'bold',\n color: 'white',\n backgroundColor: 'green',\n padding: '5px',\n paddingLeft: '10px',\n paddingRight: '10px',\n borderRadius: '5px'\n }\n\n const stopped = {\n fontSize: '12px',\n fontWeight: 'bold',\n color: 'white',\n backgroundColor: 'red',\n padding: '5px',\n paddingLeft: '10px',\n paddingRight: '10px',\n borderRadius: '5px'\n }\n\n return (\n \n
\n { props.title } \n
\n
\n { props.status } \n
\n
\n );\n}\n\nexport default Component\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\nimport Component from '../system/Component.js'\nconst ReactMarkdown = require('react-markdown')\n\n\nclass System extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n components: [],\n git: {\n version: '',\n description: '',\n code: 0\n },\n version: '',\n upgrading: false,\n show_system_message: false,\n system_message: ''\n }\n\n this.loadComponents = this.loadComponents.bind(this);\n this.upgrade = this.upgrade.bind(this);\n this.areYouAwake = this.areYouAwake.bind(this);\n this.restart = this.restart.bind(this);\n this.reboot = this.reboot.bind(this);\n this.shutdown = this.shutdown.bind(this);\n }\n\n componentDidMount() {\n\n this.loadComponents();\n setInterval(this.loadComponents,3000)\n\n var vers = new XMLHttpRequest();\n vers.onload = function (e) {\n if (vers.readyState === 4) {\n if (vers.status === 200) {\n var version = JSON.parse(vers.responseText);\n this.setState({ version: version.version });\n } else {\n console.error(vers.statusText);\n }\n }\n }.bind(this);\n vers.open(\"GET\", root + \"api/global/version/\");\n vers.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n vers.send();\n\n var git = new XMLHttpRequest();\n git.onload = function (e) {\n if (git.readyState === 4) {\n if (git.status === 200) {\n const latestRelease = JSON.parse(git.responseText);\n const description = latestRelease.body\n this.setState({ git: {\n version: latestRelease.tag_name,\n description: description,\n code: 200\n }\n });\n } else if (git.status === 403) {\n this.setState({ git: {\n version: 'GitHub rate limit exceeded. You have reloaded so many times. It will reset after some time.',\n code: 403\n }\n });\n } else {\n console.error(git.statusText);\n }\n }\n }.bind(this);\n git.open(\"GET\", 'https://api.github.com/repos/kikeelectronico/Homeware-LAN/releases/latest');\n git.send();\n }\n\n loadComponents() {\n var comp = new XMLHttpRequest();\n comp.onload = function (e) {\n if (comp.readyState === 4) {\n if (comp.status === 200) {\n var response = JSON.parse(comp.responseText);\n var components = []\n var keys = Object.keys(response);\n for (var i = 0; i < keys.length; i++) {\n components.push(response[keys[i]])\n }\n\n this.setState({ components: components });\n } else {\n console.error(comp.statusText);\n }\n }\n }.bind(this);\n comp.open(\"GET\", root + \"api/system/status/\");\n comp.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n comp.send();\n }\n\n upgrade(){\n if(window.confirm('Are you sure?')){\n window.open(root + \"files/buckup/homeware/\" + getCookieValue('token'))\n this.setState({\n show_system_message: true,\n system_message: 'Upgrading the system. It will take a couple of minutes and then you will be redirected to the home page.'\n });\n window.setTimeout(function() {\n var upg = new XMLHttpRequest();\n upg.onload = function (e) {\n if (upg.readyState === 4) {\n setInterval(this.areYouAwake,2000);\n }\n }.bind(this)\n upg.open(\"GET\", root + \"api/system/upgrade/\");\n upg.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n upg.send();\n }.bind(this),2000);\n }\n }\n\n areYouAwake(){\n var awa = new XMLHttpRequest();\n awa.onload = function (e) {\n if (awa.readyState === 4) {\n if (awa.status === 200) {\n window.location.href = '/'\n } else {\n console.error(awa.statusText);\n }\n }\n }\n awa.open(\"GET\", root + \"test/\");\n awa.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n awa.send();\n }\n\n restart(){\n this.setState({\n show_system_message: true,\n system_message: 'Restarting Homeware. It will take a couple of minutes and then you will be redirected to the home page.'\n });\n var res = new XMLHttpRequest();\n res.onload = function (e) {\n if (res.readyState === 4) {\n setInterval(this.areYouAwake,2000);\n }\n }.bind(this)\n res.open(\"GET\", root + \"api/system/restart\");\n res.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n res.send();\n }\n\n reboot(){\n this.setState({\n show_system_message: true,\n system_message: 'Rebooting the system. It will take a couple of minutes and then you will be redirected to the home page.'\n });\n var reb = new XMLHttpRequest();\n reb.onload = function (e) {\n if (reb.readyState === 4) {\n setInterval(this.areYouAwake,2000);\n }\n }.bind(this)\n reb.open(\"GET\", root + \"api/system/reboot\");\n reb.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n reb.send();\n }\n\n shutdown(){\n this.setState({\n show_system_message: true,\n system_message: 'The system will be shut down, you will lose the connection with Homeware.'\n });\n var shu = new XMLHttpRequest();\n shu.open(\"GET\", root + \"api/system/shutdown\");\n shu.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n shu.send();\n }\n\n render() {\n\n const upgrade_button = {\n width: '200px'\n }\n\n const git_description = {\n marginTop: '20px',\n marginLeft: '10%',\n width: '80%',\n paddingLeft: '20px',\n paddingRight: '20px',\n paddingTop: '20px',\n paddingBottom: '20px',\n borderRadius: '20px',\n border: '1px solid #aaa',\n textAlign: 'left'\n }\n\n const components = this.state.components.map((component) =>\n \n );\n\n return (\n \n {\n this.state.show_system_message\n ?\n
\n
System message \n
\n
\n { this.state.system_message }\n
\n
\n :\n
\n
\n
System status \n
\n
\n { components }\n
\n
\n These are the core elements of Homeware-LAN. All must be running. \n
\n
\n\n
\n
Version \n
\n
\n
System version: { this.state.version }\n {\n this.state.version !== this.state.git.version\n ?\n
\n
New version: { this.state.git.version}\n
\n \n Upgrade \n
\n
\n :\n ' - The system is up to date.'\n }\n\n
\n
\n Verify if there is any code update and upgrade if necessary. \n
\n
\n\n
\n
Power \n
\n
\n Restart Homeware \n Reboot System \n Shutdown System \n
\n
\n Control the device and restart the Homeware-LAN installation. \n
\n
\n
\n }\n\n
\n );\n }\n}\n\nexport default System\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Backup extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n }\n }\n\n backup(){\n window.location = root + \"files/buckup/homeware/\" + getCookieValue('token')\n }\n\n render() {\n\n const button = {\n width: '200px'\n }\n\n const restore_url = root + \"files/restore/file/\" + getCookieValue('token') + \"/\";\n\n return (\n \n\n\n
\n
Backup \n
\n
\n Backup \n
\n
\n Download a backup file. \n
\n
\n\n
\n
Restore \n
\n
\n \n
\n
\n Restore a backup file. \n
\n
\n\n\n
\n );\n }\n}\n\nexport default Backup\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Access extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: {\n apikey: ''\n }\n }\n }\n\n componentDidMount() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({ data: data });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/access/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n generateAPIKey(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n // var data = JSON.parse(http.responseText);\n window.location.href = \"/access\"\n } else {\n console.error(http.statusText);\n }\n }\n };\n http.open(\"GET\", root + \"api/settings/apikey/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n render() {\n\n return (\n \n
\n
API key \n
\n
\n
\n
\n API Key\n
\n
\n \n
\n
\n
\n
\n Generate \n\n
\n
\n The API Key gives you access to the Homeware's API. Please do not generate an API Key if you are not sure of what you are doing. \n
\n
\n
\n );\n }\n}\n\nexport default Access\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Logs extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: [],\n page: 1\n }\n\n this.previousPage = this.previousPage.bind(this);\n this.nextPage = this.nextPage.bind(this);\n this.downloadLog = this.downloadLog.bind(this);\n }\n\n componentDidMount() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({ data: data });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/log/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n previousPage() {\n if (this.state.page > 1)\n this.setState({ page: this.state.page - 1 });\n }\n\n nextPage() {\n if (this.state.page < this.state.data.length/10-1)\n this.setState({ page: this.state.page + 1 });\n }\n\n downloadLog() {\n window.location = root + \"files/log/homeware/\" + getCookieValue('token')\n }\n\n render() {\n\n const line = {\n width: '80%',\n marginLeft: '8%',\n marginTop: '10px',\n borderBottom: '1px solid #eee',\n paddingLeft: '20px',\n paddingBottom: '10px',\n paddingRight: '20px',\n textAlign: 'left'\n }\n\n const yellow = {\n color: 'orange'\n }\n\n const red = {\n color: 'red'\n }\n\n const homeware_lan_log_data = this.state.data.reverse().slice(0, this.state.page * 10);\n const homeware_lan_log = homeware_lan_log_data.map((register, i) =>\n \n { register.severity === 'Log' ? { register.severity } : '' }\n { register.severity === 'Warning' ? { register.severity } : '' }\n { register.severity === 'Alert' ? { register.severity } : '' }\n - { register.time } \n { register.message }\n
\n );\n\n return (\n \n
\n
Homeware-LAN log \n
\n
\n { homeware_lan_log }\n
\n
\n Load more \n Download \n
\n
\n
\n );\n }\n}\n\nexport default Logs\n","import React from 'react';\nimport { root } from '../../constants'\n\nclass Login extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n enable_message: false,\n message: ''\n }\n this.login = this.login.bind(this);\n this.grantAccess = this.grantAccess.bind(this);\n }\n\n login() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n var response = JSON.parse(http.responseText);\n if(response['status'] === 'in'){\n document.cookie = \"user=\" + response['user'] + \"; path=/\";\n document.cookie = \"token=\" + response['token'] + \"; path=/\";\n window.location = '/';\n } else if (response['status'] === 'fail'){\n this.setState({\n enable_message: true,\n message: 'Incorrect User or Password'\n })\n setTimeout(function(){\n this.setState({\n enable_message: false\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/user/login/\");\n http.setRequestHeader('user', document.getElementById('user').value)\n http.setRequestHeader('pass', document.getElementById('password').value)\n http.send();\n }\n\n grantAccess() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.responseText !== 'fail')\n window.location = http.responseText;\n else {\n this.setState({\n enable_message: true,\n message: 'Incorrect User or Password'\n })\n setTimeout(function(){\n this.setState({\n enable_message: false\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/user/googleSync/\");\n http.setRequestHeader('user', document.getElementById('user').value)\n http.setRequestHeader('pass', document.getElementById('password').value)\n http.send();\n }\n\n render() {\n\n const form_container = {\n margin: '20%',\n }\n\n const element = {\n margin: '10px'\n }\n\n var message = '';\n if (this.state.enable_message){\n message = { this.state.message }
\n }\n\n return (\n \n { window.location.href.includes('google') ?
Google request access to Homeware-Lan
: '' }\n
\n
Username \n
\n
Password \n
\n
{ !window.location.href.includes('google') ? Login : Grant access } \n
\n { message }\n
\n );\n }\n}\n\nexport default Login\n","import React from 'react';\nimport './App.css';\nimport { BrowserRouter as Router, Route } from 'react-router-dom'\nimport getCookieValue from './functions'\nimport { root } from './constants'\n\nimport Menu from './components/web/Menu'\nimport Devices from './components/pages/Devices'\nimport Editor from './components/pages/Editor'\nimport Info from './components/pages/Info'\nimport Connecting from './components/pages/Connecting'\nimport Tasks from './components/pages/Tasks'\nimport Manager from './components/pages/Manager'\nimport Settings from './components/pages/Settings'\nimport System from './components/pages/System'\nimport Backup from './components/pages/Backup'\nimport Access from './components/pages/Access'\nimport Logs from './components/pages/Logs'\nimport Login from './components/pages/Login'\n\nclass App extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n session: false,\n version: ''\n }\n this.logout = this.logout.bind(this);\n this.menu = this.menu.bind(this);\n }\n\n componentDidMount() {\n if (!window.location.href.includes('assistant')) {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n if (data.status !== 'in' && !window.location.href.includes('login'))\n window.location.href = '/login/'\n else if (data.status === 'in')\n this.setState({\n session: true\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/user/validateToken/\");\n http.setRequestHeader('token', getCookieValue('token'))\n http.setRequestHeader('user', getCookieValue('user'))\n http.send();\n\n var vers = new XMLHttpRequest();\n vers.onload = function (e) {\n if (vers.readyState === 4) {\n if (vers.status === 200) {\n var version = JSON.parse(vers.responseText);\n this.setState({ version: version.version });\n } else {\n console.error(vers.statusText);\n }\n }\n }.bind(this);\n vers.open(\"GET\", root + \"api/global/version/\");\n vers.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n vers.send();\n }\n }\n\n logout() {\n document.cookie = \"user=; path=/\";\n document.cookie = \"token=; path=/\";\n this.setState({\n session: false\n });\n window.location.href = '/'\n }\n\n menu() {\n document.getElementById('menuIcon').classList.toggle(\"change_menu_icon\");\n document.getElementById('menu').classList.toggle(\"menu_show_up\");\n }\n\n render() {\n\n if (!this.state.session && !window.location.href.includes('login'))\n return ''\n else if (window.location.href.includes('login'))\n return (\n \n \n
\n );\n else\n return (\n \n \n
\n \n
\n
Homeware-LAN \n \n
\n
\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n \n );\n }\n}\n\nexport default App;\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' },\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready\n .then(registration => {\n registration.unregister();\n })\n .catch(error => {\n console.error(error.message);\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""}
\ No newline at end of file
diff --git a/front/build/static/js/main.f5e71cab.chunk.js b/front/build/static/js/main.f5e71cab.chunk.js
deleted file mode 100644
index 0fb19f7ee..000000000
--- a/front/build/static/js/main.f5e71cab.chunk.js
+++ /dev/null
@@ -1,2 +0,0 @@
-(this.webpackJsonpHomeware=this.webpackJsonpHomeware||[]).push([[0],{13:function(e,t,a){},139:function(e,t,a){"use strict";a.r(t);var i=a(0),n=a.n(i),s=a(40),r=a.n(s),c=(a(48),a(1)),l=a(2),o=a(5),d=a(4),m=a(3),u=(a(49),a(41)),p=a(7);var v=function(e){for(var t=e+"=",a=decodeURIComponent(document.cookie).split(";"),i=0;i"),n.a.createElement("option",null,"<="),n.a.createElement("option",null,">=")))),i,n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTriggerOperation},"Save"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel")))}}]),a}(n.a.Component),Ae=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={device_a:"",device_b:""},i.updateDependencies=i.updateDependencies.bind(Object(o.a)(i)),i.addTriggerOperation=i.addTriggerOperation.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"updateDependencies",value:function(e){var t=this.state;t[e.target.id]=e.target.value,this.setState(t)}},{key:"addTriggerOperation",value:function(){var e=document.getElementById("device_a").value+":"+document.getElementById("param_a").value+":"+document.getElementById("comparator").value+":"+document.getElementById("device_b").value+":"+document.getElementById("param_b").value;this.props.addTriggerOperation("d2d",e),this.props.closeTriggerAssistant()}},{key:"render",value:function(){var e=this,t=Object.keys(this.props.devices).map((function(t){return n.a.createElement("option",{key:t,value:t},e.props.devices[t])})),a=""===this.state.device_a?"":Object.keys(this.props.status[this.state.device_a]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")})),i=""===this.state.device_b?"":Object.keys(this.props.status[this.state.device_b]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")}));return n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"Compare two devices"),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device A*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device_a",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param A*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param_a",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a param"),a))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Comparator*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"comparator"},n.a.createElement("option",null,"="),n.a.createElement("option",null,"<"),n.a.createElement("option",null,">"),n.a.createElement("option",null,"<="),n.a.createElement("option",null,">=")))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device B*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device_b",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param B*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param_b",onChange:this.updateDependencies},n.a.createElement("option",{value:""},"Select a param"),i))),n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTriggerOperation},"Save"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel")))}}]),a}(n.a.Component),De=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={type:""},i.timeTigger=i.timeTigger.bind(Object(o.a)(i)),i.deiceTrigger=i.deiceTrigger.bind(Object(o.a)(i)),i.deviceToDeviceTrigger=i.deviceToDeviceTrigger.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"timeTigger",value:function(){this.setState({type:"time"})}},{key:"deiceTrigger",value:function(){this.setState({type:"device"})}},{key:"deviceToDeviceTrigger",value:function(){this.setState({type:"device2device"})}},{key:"render",value:function(){return""===this.state.type?n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"Add a new trigger"),n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.timeTigger},"Time"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.deiceTrigger},"Device"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.deviceToDeviceTrigger},"Device to device"),n.a.createElement("button",{type:"button",className:"trigger_assistant_button red_button",onClick:this.props.closeTriggerAssistant},"Cancel"))):"time"===this.state.type?n.a.createElement(Me,{closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):"device"===this.state.type?n.a.createElement(Le,{devices:this.props.devices,status:this.props.status,closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):"device2device"===this.state.type?n.a.createElement(Ae,{devices:this.props.devices,status:this.props.status,closeTriggerAssistant:this.props.closeTriggerAssistant,addTriggerOperation:this.props.addTriggerOperation}):void 0}}]),a}(n.a.Component),Ie=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).delete=i.delete.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"delete",value:function(){this.props.delete(this.props.id)}},{key:"render",value:function(){return n.a.createElement("div",{className:"trigger_device_container",style:{marginBottom:"10px"}},n.a.createElement("span",null,(this.props.devices[this.props.target.device]?this.props.devices[this.props.target.device]:this.props.target.device)+" ("+(b.params[this.props.target.param]?b.params[this.props.target.param].name:this.props.target.param)+") = "+this.props.target.value),n.a.createElement("img",{src:"/global/bin_icon.png",alt:"Delete icon",className:"trigger_delete",onClick:this.delete}))}}]),a}(n.a.Component),He=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={device:""},i.updateDevice=i.updateDevice.bind(Object(o.a)(i)),i.updateParam=i.updateParam.bind(Object(o.a)(i)),i.addTarget=i.addTarget.bind(Object(o.a)(i)),i.typeConversion=i.typeConversion.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"updateDevice",value:function(e){this.setState({device:e.target.value})}},{key:"updateParam",value:function(e){this.setState({param:e.target.value})}},{key:"addTarget",value:function(){var e={device:document.getElementById("device").value,param:document.getElementById("param").value,value:document.getElementById("value").value};this.props.addTarget(e),document.getElementById("device").value="",document.getElementById("param").value="",this.setState({param:""})}},{key:"typeConversion",value:function(e){return{int:"d2i",list:"d2l",bool:"d2b",string:"d2s",color:"d2c"}[e]}},{key:"render",value:function(){var e=this,t=Object.keys(this.props.devices).map((function(t){return n.a.createElement("option",{key:t,value:t},e.props.devices[t])})),a=""===this.state.device?"":Object.keys(this.props.status[this.state.device]).map((function(e){return n.a.createElement("option",{key:e,value:e},b.params[e]?b.params[e].name:e+" - Not supported yet")})),i="";if(b.params[this.state.param]){var s=this.typeConversion(b.params[this.state.param].type);if("d2i"===s)i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"number",className:"",id:"value"})));else if("d2s"===s)i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"",id:"value"})));else if("d2b"===s||"d2l"===s){var r=b.params[this.state.param].select.map((function(e){return n.a.createElement("option",{key:e,value:e},e)}));i=n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Value*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"value"},r)))}}return n.a.createElement("div",{className:"trigger_assistant_container"},n.a.createElement("h2",{className:"trigger_assistant_title"},"New target"),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Device*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"device",onChange:this.updateDevice},n.a.createElement("option",{value:""},"Select a device"),t))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Param*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"two_input",id:"param",onChange:this.updateParam},n.a.createElement("option",{value:""},"Select a param"),a))),i,n.a.createElement("div",{className:"trigger_assisstant_buttons_container"},n.a.createElement("button",{type:"button",className:"trigger_assistant_button",onClick:this.addTarget},"Add")))}}]),a}(n.a.Component),Pe=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;Object(c.a)(this,a),i=t.call(this,e);var n=window.location.pathname.split("/")[3],s=!1;return""===n&&(s=!0),i.state={id:n,create:s,save_status:"",trigger_assistant_parent:0,task:{title:"",description:"",triggers:{},target:[]},devices:[],status:{}},i.update=i.update.bind(Object(o.a)(i)),i.save=i.save.bind(Object(o.a)(i)),i.delete=i.delete.bind(Object(o.a)(i)),i.deleteTrigger=i.deleteTrigger.bind(Object(o.a)(i)),i.addTriggerLogic=i.addTriggerLogic.bind(Object(o.a)(i)),i.openTriggerAssistant=i.openTriggerAssistant.bind(Object(o.a)(i)),i.addTriggerOperation=i.addTriggerOperation.bind(Object(o.a)(i)),i.closeTriggerAssistant=i.closeTriggerAssistant.bind(Object(o.a)(i)),i.addTarget=i.addTarget.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){var e=new XMLHttpRequest;if(e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText),i={};a.devices.forEach((function(e){i[e.id]=e.name.name})),this.setState({devices:i,status:a.status})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/global/get/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(),!this.state.create){var t=new XMLHttpRequest;t.onload=function(e){if(4===t.readyState)if(200===t.status){var a=JSON.parse(t.responseText);console.log(a),this.setState({task:a})}else console.error(t.statusText)}.bind(this),t.open("GET",h+"api/tasks/get/"+this.state.id+"/"),t.setRequestHeader("authorization","baerer "+v("token")),t.send()}}},{key:"update",value:function(e){var t=this.state.task;t[e.target.id]=e.target.value,this.setState({task:t})}},{key:"save",value:function(){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?(JSON.parse(e.responseText),this.state.create?window.location.href="/tasks":this.setState({save_status:"Saved correctly."})):(console.error(e.statusText),this.setState({save_status:"Error, the changes haven't been saved."})),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this);var t={task:this.state.task};this.state.create?e.open("POST",h+"api/tasks/create/"):(e.open("POST",h+"api/tasks/update/"),t.id=this.state.id),e.setRequestHeader("Content-Type","application/json;charset=UTF-8"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(JSON.stringify(t))}},{key:"delete",value:function(){if(window.confirm("Do you want to delete the task?")){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?window.location.href="/tasks/":(console.error(e.statusText),this.setState({save_status:"Error, the device hasn't been deleted."})),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this),e.open("GET",h+"api/tasks/delete/"+this.state.id+"/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send()}else this.setState({save_status:"Ok. The device is save."})}},{key:"deleteTrigger",value:function(e){var t=this.state.task,a=t.triggers,i=a[e].parent;if("triggers"!==i){var n=a[i].operation.indexOf(e);a[i].operation.splice(n,1),delete a[e],t.triggers=a}else t.triggers={};this.setState({task:t})}},{key:"addTriggerLogic",value:function(e,t){var a=this.state.task;if("triggers"!==t){var i=Date.now();a.triggers[i]={operation:[],parent:t,type:e},a.triggers[t].operation.push(i)}else a.triggers.trigger={operation:[],parent:"triggers",type:e};this.setState({task:a})}},{key:"openTriggerAssistant",value:function(e){this.setState({trigger_assistant_parent:e})}},{key:"addTriggerOperation",value:function(e,t){var a=this.state.task,i=this.state.trigger_assistant_parent;if("triggers"!==i){var n=Date.now();a.triggers[n]={operation:t,parent:i,type:e},a.triggers[i].operation.push(n)}else a.triggers.trigger={operation:t,parent:"triggers",type:e};this.setState({task:a})}},{key:"closeTriggerAssistant",value:function(){this.setState({trigger_assistant_parent:0})}},{key:"addTarget",value:function(e){var t=this.state.task;t.target.push(e),this.setState({task:t})}},{key:"render",value:function(){var e=this,t=this.state.task.target.map((function(t,a){return n.a.createElement(Ie,{key:a,target:t,devices:e.state.devices})}));return n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"Task"),n.a.createElement("hr",{style:{width:"70%"}}),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Name*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"title",defaultValue:this.state.task.title,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Description*"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"description",defaultValue:this.state.task.description,onChange:this.update}))),n.a.createElement("hr",null),n.a.createElement("h2",null,"Triggers"),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null)),0!==this.state.trigger_assistant_parent?n.a.createElement(De,{devices:this.state.devices,status:this.state.status,closeTriggerAssistant:this.closeTriggerAssistant,addTriggerOperation:this.addTriggerOperation}):n.a.createElement(Re,{id:"trigger",triggers:this.state.task.triggers,devices:this.state.devices,delete:this.deleteTrigger,addTriggerLogic:this.addTriggerLogic,openTriggerAssistant:this.openTriggerAssistant}),n.a.createElement("hr",null),n.a.createElement("h2",null,"Targets"),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null)),t,n.a.createElement(He,{devices:this.state.devices,status:this.state.status,addTarget:this.addTarget}),n.a.createElement("hr",null),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("button",{type:"button",style:this.state.create?{backgroundColor:"red",opacity:"0.2"}:{backgroundColor:"red"},onClick:this.delete,disabled:!!this.state.create},"Delete"),n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status))))}}]),a}(n.a.Component),Fe=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={settings:{google:{},ddns:{},mqtt:{},apikey:""},save_status:"",url:{auth:"",token:"",fulfillment:""}},i.update=i.update.bind(Object(o.a)(i)),i.enableDdnsProvider=i.enableDdnsProvider.bind(Object(o.a)(i)),i.save=i.save.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){if(!this.state.create){var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText);this.setState({settings:a,url:{auth:"https://"+a.ddns.hostname+"/auth/",token:"https://"+a.ddns.hostname+"/token/",fulfillment:"https://"+a.ddns.hostname+"/smarthome/"}})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/settings/get/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send()}}},{key:"update",value:function(e){var t=e.target.id.split("/"),a=this.state.settings;1===t.length?a[t[0]]=e.target.value:2===t.length&&(a[t[0]][t[1]]=e.target.value),this.setState({settings:a})}},{key:"enableDdnsProvider",value:function(e){var t=this.state.settings;t.ddns.enabled=e,this.setState({settings:t})}},{key:"save",value:function(){var e=new XMLHttpRequest;e.onload=function(t){4===e.readyState&&(200===e.status?(JSON.parse(e.responseText),this.setState({save_status:"Saved correctly."})):this.setState({save_status:"Error, the changes haven't been saved."}),setTimeout(function(){this.setState({save_status:""})}.bind(this),5e3))}.bind(this),e.open("POST",h+"api/settings/update/"),e.setRequestHeader("Content-Type","application/json;charset=UTF-8"),e.setRequestHeader("authorization","baerer "+v("token")),e.send(JSON.stringify(this.state.settings))}},{key:"render",value:function(){return n.a.createElement("div",null,n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"Actions on Google"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Client ID"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"google/client_id",defaultValue:this.state.settings.google.client_id,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Client Secret"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"google/client_secret",defaultValue:this.state.settings.google.client_secret,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Authorization URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.auth,disabled:!0}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Token URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.token,disabled:!0}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Fulfillment URL"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",defaultValue:this.state.url.fulfillment,disabled:!0})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Actions on Google settings. It is used to authenticate with Google. If you change it here, you must change it on the Actions Console > Develop > Account Linking."))),n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"MQTT"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"User"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"mqtt/user",defaultValue:this.state.settings.mqtt.user,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Password"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"mqtt/password",defaultValue:this.state.settings.mqtt.password,onChange:this.update})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Important. You must configure the username and password into Mosquitto manually from a terminal. This is only for telling Homeware its credentials. Clear both if you don't use credentials."))),n.a.createElement("div",{className:"page_block_container"},n.a.createElement("h2",null,"DDNS provider"),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Status:"),n.a.createElement("div",{className:"two_table_cel"},this.state.settings.ddns.status)),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"IP and time:"),n.a.createElement("div",{className:"two_table_cel"},this.state.settings.ddns.ip+" updated at "+this.state.settings.ddns.last))),n.a.createElement("hr",null),n.a.createElement("div",{className:"page_block_content_container"},n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Enable"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement(ie.a,{onChange:this.enableDdnsProvider,checked:this.state.settings.ddns.enabled}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Provider"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("select",{name:"type",className:"settings_select",id:"ddns/provider",value:this.state.settings.ddns.provider,onChange:this.update},n.a.createElement("option",{value:"noip"},"Noip")))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Username"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/username",defaultValue:this.state.settings.ddns.username,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Password"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/password",defaultValue:this.state.settings.ddns.password,onChange:this.update}))),n.a.createElement("div",{className:"two_table_row"},n.a.createElement("div",{className:"two_table_cel"},"Hostname"),n.a.createElement("div",{className:"two_table_cel"},n.a.createElement("input",{type:"text",className:"two_input",id:"ddns/hostname",defaultValue:this.state.settings.ddns.hostname,onChange:this.update})))),n.a.createElement("div",{className:"page_block_buttons_container"},n.a.createElement("button",{type:"button",onClick:this.save},"Save"),n.a.createElement("span",null,this.state.save_status)),n.a.createElement("div",{className:"advise"},n.a.createElement("span",null,"Set up the access data to the DDNS provider account. Open an issue on Github if you want a DDNS provider that is not listed."))))}}]),a}(n.a.Component);var qe=function(e){return n.a.createElement("div",{style:{marginTop:"5px",width:"100%",display:"grid",gridTemplateColumns:"70% 30%"}},n.a.createElement("div",{style:{textAlign:"left",paddingTop:"4px"}},n.a.createElement("span",{style:{fontSize:"18px"}},e.title)),n.a.createElement("div",{style:{textAlign:"right",paddingTop:"4px"}},n.a.createElement("span",{style:"Running"===e.status?{fontSize:"12px",fontWeight:"bold",color:"white",backgroundColor:"green",padding:"5px",paddingLeft:"10px",paddingRight:"10px",borderRadius:"5px"}:{fontSize:"12px",fontWeight:"bold",color:"white",backgroundColor:"red",padding:"5px",paddingLeft:"10px",paddingRight:"10px",borderRadius:"5px"}},e.status)))},Ge=a(54),Ue=function(e){Object(d.a)(a,e);var t=Object(m.a)(a);function a(e){var i;return Object(c.a)(this,a),(i=t.call(this,e)).state={components:[],git:{version:"",description:"",code:0},version:"",upgrading:!1,show_system_message:!1,system_message:""},i.loadComponents=i.loadComponents.bind(Object(o.a)(i)),i.upgrade=i.upgrade.bind(Object(o.a)(i)),i.areYouAwake=i.areYouAwake.bind(Object(o.a)(i)),i.restart=i.restart.bind(Object(o.a)(i)),i.reboot=i.reboot.bind(Object(o.a)(i)),i.shutdown=i.shutdown.bind(Object(o.a)(i)),i}return Object(l.a)(a,[{key:"componentDidMount",value:function(){this.loadComponents(),setInterval(this.loadComponents,3e3);var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){var a=JSON.parse(e.responseText);this.setState({version:a.version})}else console.error(e.statusText)}.bind(this),e.open("GET",h+"api/global/version/"),e.setRequestHeader("authorization","baerer "+v("token")),e.send();var t=new XMLHttpRequest;t.onload=function(e){if(4===t.readyState)if(200===t.status){var a=JSON.parse(t.responseText),i=a.body;this.setState({git:{version:a.tag_name,description:i,code:200}})}else 403===t.status?this.setState({git:{version:"GitHub rate limit exceeded. You have reloaded so many times. It will reset after some time.",code:403}}):console.error(t.statusText)}.bind(this),t.open("GET","https://api.github.com/repos/kikeelectronico/Homeware-LAN/releases/latest"),t.send()}},{key:"loadComponents",value:function(){var e=new XMLHttpRequest;e.onload=function(t){if(4===e.readyState)if(200===e.status){for(var a=JSON.parse(e.responseText),i=[],n=Object.keys(a),s=0;s1&&this.setState({page:this.state.page-1})}},{key:"nextPage",value:function(){this.state.page\n \n
\n
\n \n { props.title } \n
\n \n );\n}\n\nexport default Menu\n","import React from 'react';\nimport getCookieValue from '../../../functions'\nimport { root } from '../../../constants'\n\nclass OnOff extends React.Component {\n constructor(props) {\n super(props);\n this.toggle = this.toggle.bind(this);\n }\n\n toggle(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n this.props.reload();\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this)\n http.open(\"POST\", root + \"api/status/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify({\n \"id\": this.props.id,\n \"param\": \"on\",\n \"value\": !this.props.on\n }));\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default OnOff\n","import React from 'react';\n\nclass Information extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/info/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default Information\n","import React from 'react';\n\nclass Connecting extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/connecting/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default Connecting\n","import React from 'react';\n\nclass Edit extends React.Component {\n constructor(props) {\n super(props);\n this.go = this.go.bind(this);\n }\n\n go(){\n window.location.href = \"/devices/editor/\" + this.props.id + \"/\"\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n return (\n \n
\n
\n );\n }\n}\n\nexport default Edit\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Light extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n if (Object.keys(this.props.status.color).includes(\"spectrumRgb\"))\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n else\n color = \"#\" + this.props.status.color.spectrumRGB.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Light\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Outlet extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'blue',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Outlet\n","import React from 'react';\nimport getCookieValue from '../../../functions'\nimport { root } from '../../../constants'\n\nclass TemperatureSetting extends React.Component {\n constructor(props) {\n super(props);\n this.up = this.up.bind(this);\n this.down = this.down.bind(this);\n this.update = this.update.bind(this);\n }\n\n up(){\n var temperature = this.props.status.thermostatTemperatureSetpoint + 1;\n this.update(temperature)\n }\n\n down(){\n var temperature = this.props.status.thermostatTemperatureSetpoint - 1;\n this.update(temperature)\n }\n\n update(temperature){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n this.props.reload();\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this)\n http.open(\"POST\", root + \"api/status/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify({\n \"id\": this.props.id,\n \"param\": \"thermostatTemperatureSetpoint\",\n \"value\": temperature\n }));\n }\n\n render() {\n\n const container = {\n float: 'left',\n marginLeft: '5px'\n }\n\n const image = {\n width: '30px'\n }\n\n const temperature = {\n fontSize: '30px',\n marginLeft: '5px',\n marginRight: '5px',\n color: '#777'\n }\n\n return (\n \n
\n
{this.props.status.thermostatTemperatureSetpoint} \n
\n
\n );\n }\n}\n\nexport default TemperatureSetting\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport TemperatureSetting from './traits/TemperatureSetting'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AcUnit extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.status.thermostatMode === 'off')\n color = \"#666\";\n else if (this.props.status.thermostatMode === 'heat')\n color = \"red\";\n else if (this.props.status.thermostatMode === 'cool')\n color = \"lightblue\";\n else if (this.props.status.thermostatMode === 'on')\n color = \"yellow\";\n else if (this.props.status.thermostatMode === 'heatcool')\n color = \"#DC97FF\";\n else if (this.props.status.thermostatMode === 'auto')\n color = \"#EE357E\";\n else if (this.props.status.thermostatMode === 'fan-only')\n color = \"blue\";\n else if (this.props.status.thermostatMode === 'purifier')\n color = \"#F3882E\";\n else if (this.props.status.thermostatMode === 'eco')\n color = \"green\";\n else if (this.props.status.thermostatMode === 'dry')\n color = \"#753500\";\n\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AcUnit\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirFreshener extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirFreshener\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirPurifier extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirPurifier\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Bed extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Bed\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Fan extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Fan\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Fireplace extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Fireplace\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Radiator extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Radiator\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Switch extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'yellow',\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Switch\n","import React from 'react';\nimport TemperatureSetting from './traits/TemperatureSetting'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Thermostat extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.status.thermostatMode === 'off')\n color = \"#666\";\n else if (this.props.status.thermostatMode === 'heat')\n color = \"red\";\n else if (this.props.status.thermostatMode === 'cool')\n color = \"lightblue\";\n else if (this.props.status.thermostatMode === 'on')\n color = \"yellow\";\n else if (this.props.status.thermostatMode === 'heatcool')\n color = \"#DC97FF\";\n else if (this.props.status.thermostatMode === 'auto')\n color = \"#EE357E\";\n else if (this.props.status.thermostatMode === 'fan-only')\n color = \"blue\";\n else if (this.props.status.thermostatMode === 'purifier')\n color = \"#F3882E\";\n else if (this.props.status.thermostatMode === 'eco')\n color = \"green\";\n else if (this.props.status.thermostatMode === 'dry')\n color = \"#753500\";\n\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Thermostat\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass AirCooler extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default AirCooler\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Bathtub extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Bathtub\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Awing extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Awing\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Blinds extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Blinds\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Closet extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Closet\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Curtain extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Curtain\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Door extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Door\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Drawer extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Drawer\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Garage extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Garage\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Pergola extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Pergola\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Shutter extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Shutter\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Valve extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Valve\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Window extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Window\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Lock extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Lock\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Gate extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Gate\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Heater extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Heater\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Hood extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Hood\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass SecuritySystem extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: 'white',\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default SecuritySystem\n","import React from 'react';\nimport OnOff from './traits/OnOff'\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Blender extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'yellow';\n if (this.props.device.traits.includes(\"action.devices.traits.ColorSetting\")){\n color = \"#\" + this.props.status.color.spectrumRgb.toString(16);\n }\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color,\n opacity: this.props.status.on ? '1' : '0.4'\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Blender\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Global extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'white';\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n \n
\n
\n
{ this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Global\n","import React from 'react';\nimport Information from './aux/Information'\nimport Connecting from './aux/Connecting'\nimport Edit from './aux/Edit'\n\nclass Scene extends React.Component {\n\n render() {\n\n const traits_container = {\n paddingLeft: '50px'\n }\n\n var color = 'white';\n\n const color_strip = {\n width: '100%',\n height: '20px',\n borderRadius: '20px 20px 0px 0px',\n backgroundColor: color\n }\n\n return (\n \n
\n
\n
Scene: { this.props.device.name.name } \n
\n
\n \n \n \n
\n
\n
\n );\n }\n}\n\nexport default Scene\n","import React from 'react';\nimport Light from '../devices/Light'\nimport Outlet from '../devices/Outlet'\nimport AcUnit from '../devices/AcUnit'\nimport AirFreshener from '../devices/AirFreshener'\nimport AirPurifier from '../devices/AirPurifier'\nimport Bed from '../devices/Bed'\nimport Fan from '../devices/Fan'\nimport Fireplace from '../devices/Fireplace'\nimport Radiator from '../devices/Radiator'\nimport Switch from '../devices/Switch'\nimport Thermostat from '../devices/Thermostat'\nimport AirCooler from '../devices/AirCooler'\nimport Bathtub from '../devices/Bathtub'\nimport Awing from '../devices/Awing'\nimport Blinds from '../devices/Blinds'\nimport Closet from '../devices/Closet'\nimport Curtain from '../devices/Curtain'\nimport Door from '../devices/Door'\nimport Drawer from '../devices/Drawer'\nimport Garage from '../devices/Garage'\nimport Pergola from '../devices/Pergola'\nimport Shutter from '../devices/Shutter'\nimport Valve from '../devices/Valve'\nimport Window from '../devices/Window'\nimport Lock from '../devices/Lock'\nimport Gate from '../devices/Gate'\nimport Heater from '../devices/Heater'\nimport Hood from '../devices/Hood'\nimport SecuritySystem from '../devices/SecuritySystem'\nimport Blender from '../devices/Blender'\nimport Global from '../devices/Global'\nimport Scene from '../devices/Scene'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Devices.css';\n\nclass Devices extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: {},\n devices: []\n }\n this.loadData = this.loadData.bind(this);\n this.newDevice = this.newDevice.bind(this);\n }\n\n componentDidMount() {\n this.loadData();\n setInterval(this.loadData,3000);\n }\n\n loadData(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n data: data,\n devices: data.devices\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/global/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n newDevice(){\n window.location.href = '/devices/editor/'\n }\n\n render() {\n\n const devices = this.state.devices.map((device) => {\n if(device.type === 'action.devices.types.LIGHT')\n return \n else if(device.type === 'action.devices.types.OUTLET')\n return \n else if(device.type === 'action.devices.types.AC_UNIT')\n return \n else if(device.type === 'action.devices.types.AIRFRESHENER')\n return \n else if(device.type === 'action.devices.types.AIRPURIFIER')\n return \n else if(device.type === 'action.devices.types.BED')\n return \n else if(device.type === 'action.devices.types.FAN')\n return \n else if(device.type === 'action.devices.types.FIREPLACE')\n return \n else if(device.type === 'action.devices.types.RADIATOR')\n return \n else if(device.type === 'action.devices.types.SWITCH')\n return \n else if(device.type === 'action.devices.types.THERMOSTAT')\n return \n else if(device.type === 'action.devices.types.AIRCOOLER')\n return \n else if(device.type === 'action.devices.types.BATHTUB')\n return \n else if(device.type === 'action.devices.types.AWING')\n return \n else if(device.type === 'action.devices.types.AIRCOOLER')\n return \n else if(device.type === 'action.devices.types.BLINDS')\n return \n else if(device.type === 'action.devices.types.CLOSET')\n return \n else if(device.type === 'action.devices.types.CURTAIN')\n return \n else if(device.type === 'action.devices.types.DOOR')\n return \n else if(device.type === 'action.devices.types.DRAWER')\n return \n else if(device.type === 'action.devices.types.GARAGE')\n return \n else if(device.type === 'action.devices.types.GATE')\n return \n else if(device.type === 'action.devices.types.PERGOLA')\n return \n else if(device.type === 'action.devices.types.SHUTTER')\n return \n else if(device.type === 'action.devices.types.VALVE')\n return \n else if(device.type === 'action.devices.types.WINDOW')\n return \n else if(device.type === 'action.devices.types.LOCK')\n return \n else if(device.type === 'action.devices.types.HEATER')\n return \n else if(device.type === 'action.devices.types.HOOD')\n return \n else if(device.type === 'action.devices.types.SECURITYSYSTEM')\n return \n else if(device.type === 'action.devices.types.BLENDER')\n return \n else if(device.type === 'action.devices.types.SCENE')\n return \n else\n return \n });\n\n return (\n \n
\n
Devices and scences \n \n\n
\n { devices }\n
\n\n
\n New \n
\n
\n );\n }\n}\n\nexport default Devices\n","import React from 'react';\n\nimport '../pages/Editor.css';\n\nclass Text extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n }\n\n\n update(event){\n this.props.update(this.props.data,event.target.value);\n }\n\n render() {\n return (\n \n
\n {this.props.name}\n
\n
\n \n
\n
\n );\n }\n}\n\nexport default Text\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Scene extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n \n
\n
\n sceneReversible \n
\n
\n {this.updateCheckbox(checked,\"sceneReversible\")}} checked={this.props.attributes.sceneReversible} />\n
\n
\n Enable it if the scene can be desabled. \n
\n
\n
\n );\n }\n}\n\nexport default Scene\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass OnOff extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n
\n
\n commandOnlyOnOff \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyOnOff\")}} checked={this.props.attributes.commandOnlyOnOff} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state. \n
\n
\n
\n
\n queryOnlyOnOff \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyOnOff\")}} checked={this.props.attributes.queryOnlyOnOff} />\n
\n
\n Enable it if Google shouldn't change the device state. \n
\n
\n
\n );\n }\n}\n\nexport default OnOff\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Brightness extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n \n
\n
\n commandOnlyBrightness \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyBrightness\")}} checked={this.props.commandOnlyBrightness} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the brightness. \n
\n
\n
\n );\n }\n}\n\nexport default Brightness\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass FanSpeed extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateFanSpeeds = this.updateFanSpeeds.bind(this);\n this.addFanSpeed = this.addFanSpeed.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateFanSpeeds(event){\n const id = event.target.id.split('_')\n const speed_id = id[1]\n //Process the attribute and value depending of the attribute\n const speed_attribute = id[0] === 'lang' ? id[0] : 'speed_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableFanSpeeds = this.props.attributes.availableFanSpeeds\n temp_availableFanSpeeds.speeds[speed_id].speed_values[0][speed_attribute] = value\n if (id[0] === 'names') temp_availableFanSpeeds.speeds[speed_id].speed_name = value[0]\n this.props.update('attributes/availableFanSpeeds', temp_availableFanSpeeds);\n }\n\n addFanSpeed(){\n var temp_availableFanSpeeds = this.props.attributes.availableFanSpeeds\n temp_availableFanSpeeds.speeds.push({\n \"speed_name\": \"\",\n \"speed_values\": [\n {\n \"speed_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableFanSpeeds', temp_availableFanSpeeds);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const speeds = this.props.attributes.availableFanSpeeds.speeds.map((speed, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Speed name: \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n reversible \n
\n
\n {this.updateCheckbox(checked,\"reversible\")}} checked={this.props.attributes.reversible} />\n
\n
\n Enable it if the fan supports blowing in both directions. \n
\n
\n\n
\n
\n supportsFanSpeedPercent \n
\n
\n {this.updateCheckbox(checked,\"supportsFanSpeedPercent\")}} checked={this.props.attributes.supportsFanSpeedPercent} />\n
\n
\n Enable it if the speed can be controlled with a number from 0 to 100. \n
\n
\n\n
\n
\n commandOnlyFanSpeed \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyFanSpeed\")}} checked={this.props.attributes.commandOnlyFanSpeed} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the fan speed. \n
\n
\n\n
\n
\n Add a speed\n
\n
\n Add \n
\n
\n\n {speeds}\n\n
\n );\n }\n}\n\nexport default FanSpeed\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass ColorSetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n
\n
\n Color type \n
\n
\n \n Select \n RGB light \n HSV light \n Color temperature \n \n
\n
\n \n
\n
\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum color temperature (in Kelvin) supported by the device. \n
\n
\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum color temperature (in Kelvin) supported by the device. \n
\n
\n
\n
\n commandOnlyColorSetting \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyColorSetting\")}} checked={this.props.attributes.commandOnlyColorSetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the color. \n
\n
\n\n
\n );\n }\n}\n\nexport default ColorSetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass TemperatureSetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_availableThermostatModes = this.props.attributes.availableThermostatModes.split(',')\n\n if (event.target.value === 'delete'){\n temp_availableThermostatModes.splice(mode_id, 1)\n } else if (event.target.value !== 'select') {\n temp_availableThermostatModes[mode_id] = event.target.value;\n }\n\n this.props.update('attributes/availableThermostatModes', temp_availableThermostatModes.join(','));\n }\n\n addMode(){\n var temp_availableThermostatModes = this.props.attributes.availableThermostatModes\n temp_availableThermostatModes += \",\"\n this.props.update('attributes/availableThermostatModes', temp_availableThermostatModes);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n\n render() {\n\n const modes = this.props.attributes.availableThermostatModes.split(',').map((mode, i) => {\n\n return (\n \n
\n
\n
\n
\n \n Mode: \n \n Select a mode \n Delete this mode \n Off \n Heat \n Cool \n On \n Heatcool \n Auto \n Fan only \n Purifier \n Eco \n Dry \n \n \n
\n
\n
\n\n )\n });\n\n return (\n \n\n
\n
\n Add a thermostat mode\n
\n
\n Add \n
\n
\n\n {modes}\n\n
\n
\n commandOnlyTemperatureSetting \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTemperatureSetting\")}} checked={this.props.attributes.commandOnlyTemperatureSetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the temperature. \n
\n
\n\n
\n
\n queryOnlyTemperatureSetting \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyTemperatureSetting\")}} checked={this.props.attributes.queryOnlyTemperatureSetting} />\n
\n
\n Enable it if Google shouldn't change the device temperature settings. \n
\n
\n\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Range\n
\n
\n \n
\n
\n Specifies the minimum offset between heat-cool setpoints in Celsius. \n
\n
\n\n
\n
\n Units\n
\n
\n \n Celsius \n Fahrenheit \n \n
\n
\n\n\n\n
\n );\n }\n}\n\nexport default TemperatureSetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Toggles extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updatetoggle = this.updatetoggle.bind(this);\n this.addToggle = this.addToggle.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updatetoggle(event){\n const id = event.target.id.split('_')\n const toggle_id = id[1]\n //Process the attribute and value depending of the attribute\n const toggle_attribute = id[0] === 'lang' ? id[0] : 'name_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableToggles = this.props.attributes.availableToggles\n temp_availableToggles[toggle_id].name_values[0][toggle_attribute] = value\n if (id[0] === 'names') temp_availableToggles[toggle_id].name = value[0]\n this.props.update('attributes/availableToggles', temp_availableToggles);\n }\n\n addToggle(){\n var temp_availableToggles = this.props.attributes.availableToggles\n temp_availableToggles.push({\n \"name\": \"\",\n \"name_values\": [\n {\n \"name_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableToggles', temp_availableToggles);\n }\n\n render() {\n\n const names_box = {\n marginLeft: '20px',\n width: '150px'\n }\n\n const toggles = this.props.attributes.availableToggles.map((toggle, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Name: \n \n \n\n\n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n commandOnlyToggles \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyToggles\")}} checked={this.props.attributes.commandOnlyToggles} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the states. \n
\n
\n\n
\n
\n Add a toggle\n
\n
\n Add \n
\n
\n\n {toggles}\n\n
\n );\n }\n}\n\nexport default Toggles\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Modes extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_availableModes = this.props.attributes.availableModes\n\n if(id[0] === 'lang'){\n temp_availableModes[mode_id].name_values[0].lang = event.target.value;\n } else if (id[0] === 'names'){\n temp_availableModes[mode_id].name_values[0].name_synonym = event.target.value.split(',');\n temp_availableModes[mode_id].name = event.target.value.split(',')[0]\n } else if (id[0] === 'settings'){\n var values = event.target.value.split(',')\n var settings = []\n for ( var i = 0; i < values.length; i ++){\n settings.push({\n setting_name: values[i],\n setting_values: [{\n setting_synonym: [values[i]],\n lang: this.props.attributes.availableModes[mode_id].name_values[0].lang\n }]\n })\n }\n temp_availableModes[mode_id].settings = settings\n }\n this.props.update('attributes/availableModes', temp_availableModes);\n }\n\n addMode(){\n var temp_availableModes = this.props.attributes.availableModes\n temp_availableModes.push({\n \"name\": \"\",\n \"name_values\": [\n {\n \"name_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ],\n \"settings\": [\n {\n \"setting_name\": \"\",\n \"setting_values\": [{\n \"setting_synonym\": [\"\"],\n \"lang\": \"en\"\n }]\n }\n ]\n });\n this.props.update('attributes/availableModes', temp_availableModes);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const settings_box = {\n width: '230px'\n }\n\n\n const modes = this.props.attributes.availableModes.map((mode, i) => {\n const settings = mode.settings.map((setting,i) => {return setting.setting_name});\n\n return (\n \n\n )\n });\n\n return (\n \n\n
\n
\n commandOnlyModes \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyModes\")}} checked={this.props.attributes.commandOnlyModes} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the modes. \n
\n
\n\n
\n
\n Add a mode\n
\n
\n Add \n
\n
\n\n {modes}\n\n
\n );\n }\n}\n\nexport default Modes\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass HumiditySetting extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n\n
\n
\n Minimum humidity\n
\n
\n \n
\n
\n Minimum humidity level as percentage. \n
\n
\n\n
\n
\n Maximum humidity\n
\n
\n \n
\n
\n Maximum humidity level as percentage. \n
\n
\n\n
\n
\n commandOnlyHumiditySetting \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyHumiditySetting\")}} checked={this.props.attributes.commandOnlyHumiditySetting} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the humidity. \n
\n
\n\n
\n
\n queryOnlyHumiditySetting \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyHumiditySetting\")}} checked={this.props.attributes.queryOnlyHumiditySetting} />\n
\n
\n Enable it if Google shouldn't change the device humidity. \n
\n
\n\n
\n );\n }\n}\n\nexport default HumiditySetting\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass OpenClose extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n
\n
\n discreteOnlyOpenClose \n
\n
\n {this.updateCheckbox(checked,\"discreteOnlyOpenClose\")}} checked={this.props.attributes.discreteOnlyOpenClose} />\n
\n
\n Enable it if the device must either be fully open or fully closed. \n
\n
\n\n
\n
\n commandOnlyOpenClose \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyOpenClose\")}} checked={this.props.attributes.commandOnlyOpenClose} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state. \n
\n
\n\n
\n
\n queryOnlyOpenClose \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyOpenClose\")}} checked={this.props.attributes.queryOnlyOpenClose} />\n
\n
\n Enable it if Google shouldn't change the device state. \n
\n
\n\n
\n );\n }\n}\n\nexport default OpenClose\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Rotation extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n return (\n \n\n
\n
\n Minimum rotation\n
\n
\n \n
\n
\n Minimum rotation degrees that a device can rotate. \n
\n
\n\n
\n
\n Maximum rotation\n
\n
\n \n
\n
\n Maximum rotation degrees that a device can rotate. \n
\n
\n\n
\n
\n commandOnlyRotation \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyRotation\")}} checked={this.props.attributes.commandOnlyRotation} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the device. \n
\n
\n\n
\n
\n supportsContinuousRotation \n
\n
\n {this.updateCheckbox(checked,\"supportsContinuousRotation\")}} checked={this.props.attributes.supportsContinuousRotation} />\n
\n
\n Enable it if the device supports continuous rotation. \n
\n
\n\n
\n
\n supportsDegrees \n
\n
\n {this.updateCheckbox(checked,\"supportsDegrees\")}} checked={this.props.attributes.supportsDegrees} />\n
\n
\n Enable it if the device allows rotation by degree. \n
\n
\n\n
\n
\n supportsPercent \n
\n
\n {this.updateCheckbox(checked,\"supportsPercent\")}} checked={this.props.attributes.supportsPercent} />\n
\n
\n Enable it if device allows rotation by percent. \n
\n
\n\n
\n );\n }\n}\n\nexport default Rotation\n","import React from 'react';\n\nclass Fill extends React.Component {\n constructor(props) {\n super(props);\n this.updateLevels = this.updateLevels.bind(this);\n this.addLevel = this.addLevel.bind(this);\n }\n\n updateLevels(event){\n const id = event.target.id.split('_')\n const level_id = id[1]\n //Process the attribute and value depending of the attribute\n const level_attribute = id[0] === 'lang' ? id[0] : 'level_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableFillLevels = this.props.attributes.availableFillLevels\n temp_availableFillLevels.levels[level_id].level_values[0][level_attribute] = value\n if (id[0] === 'names') temp_availableFillLevels.levels[level_id].level_name = value[0]\n this.props.update('attributes/availableFillLevels', temp_availableFillLevels);\n }\n\n addLevel(){\n var temp_availableFillLevels = this.props.attributes.availableFillLevels\n temp_availableFillLevels.levels.push({\n \"level_name\": \"\",\n \"level_values\": [\n {\n \"level_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableFillLevels', temp_availableFillLevels);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const levels = this.props.attributes.availableFillLevels.levels.map((level, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Fill level name: \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n Add a level\n
\n
\n Add \n
\n
\n\n {levels}\n\n
\n );\n }\n}\n\nexport default Fill\n","import React from 'react';\n\nclass ArmDisarm extends React.Component {\n constructor(props) {\n super(props);\n this.updateSecurityLevel = this.updateSecurityLevel.bind(this);\n this.addSecurityLevel = this.addSecurityLevel.bind(this);\n }\n\n updateSecurityLevel(event){\n const id = event.target.id.split('_')\n const level_id = id[1]\n //Process the attribute and value depending of the attribute\n const level_attribute = id[0] === 'lang' ? id[0] : 'level_synonym';\n const value = id[0] === 'lang' ? event.target.value : event.target.value.split(',')\n //Update the temporal data and update it\n var temp_availableArmLevels = this.props.attributes.availableArmLevels\n temp_availableArmLevels.levels[level_id].level_values[0][level_attribute] = value\n if (id[0] === 'names') temp_availableArmLevels.levels[level_id].level_name = value[0]\n this.props.update('attributes/availableArmLevels', temp_availableArmLevels);\n }\n\n addSecurityLevel(){\n var temp_availableArmLevels = this.props.attributes.availableArmLevels\n temp_availableArmLevels.levels.push({\n \"level_name\": \"\",\n \"level_values\": [\n {\n \"level_synonym\": [\"\"],\n \"lang\": \"en\"\n }\n ]\n });\n this.props.update('attributes/availableArmLevels', temp_availableArmLevels);\n }\n\n render() {\n\n const names_box = {\n marginLeft: '20px',\n width: '150px'\n }\n\n const levels = this.props.attributes.availableArmLevels.levels.map((level, i) => {\n return (\n \n
\n
\n
\n
\n \n Languaje: \n \n es \n en \n \n \n \n Level name: \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n Add a security level\n
\n
\n Add \n
\n
\n\n {levels}\n\n
\n );\n }\n}\n\nexport default ArmDisarm\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass StartStop extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.updateArray = this.updateArray.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n updateArray(event){\n this.props.update('attributes/' + event.target.id,event.target.value.split(','));\n }\n\n render() {\n return (\n \n
\n
\n pausable \n
\n
\n {this.updateCheckbox(checked,\"pausable\")}} checked={this.props.attributes.pausable} />\n
\n
\n Enable it if the device can be paused. \n
\n
\n\n
\n
\n Zones\n
\n
\n \n
\n
\n\n
\n
\n\n
\n
\n Supported zones names separeted by commas. \n
\n
\n\n\n
\n );\n }\n}\n\nexport default StartStop\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass Timer extends React.Component {\n constructor(props) {\n super(props);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n this.update = this.update.bind(this);\n }\n\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n render() {\n return (\n \n
\n
\n commandOnlyTimer \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTimer\")}} checked={this.props.attributes.commandOnlyTimer} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the state. \n
\n
\n\n
\n
\n Max time\n
\n
\n \n
\n
\n\n
\n
\n\n
\n
\n Indicates the longest timer setting in seconds available on the device. \n
\n
\n
\n );\n }\n}\n\nexport default Timer\n","import React from 'react';\nimport Switch from \"react-switch\";\n\nclass TemperatureControl extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n this.updateCheckbox = this.updateCheckbox.bind(this);\n }\n\n update(event){\n this.props.update('attributes/' + event.target.id,event.target.value);\n }\n\n updateCheckbox(checked, attribute){\n this.props.update('attributes/' + attribute,checked);\n }\n\n render() {\n\n\n return (\n \n\n
\n
\n commandOnlyTemperatureControl \n
\n
\n {this.updateCheckbox(checked,\"commandOnlyTemperatureControl\")}} checked={this.props.attributes.commandOnlyTemperatureControl} />\n
\n
\n Enable it if Homeware-LAN shouldn't inform Google Home about the temperature. \n
\n
\n\n
\n
\n queryOnlyTemperatureControl \n
\n
\n {this.updateCheckbox(checked,\"queryOnlyTemperatureControl\")}} checked={this.props.attributes.queryOnlyTemperatureControl} />\n
\n
\n Enable it if Google shouldn't change the device temperature settings. \n
\n
\n\n
\n
\n Minimum temperature\n
\n
\n \n
\n
\n Minimum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Maximum temperature\n
\n
\n \n
\n
\n Maximum temperature (in Celsius) supported by the device. \n
\n
\n\n
\n
\n Step\n
\n
\n \n
\n
\n Specifies the relative temperature step. \n
\n
\n\n
\n
\n Units\n
\n
\n \n Celsius \n Fahrenheit \n \n
\n
\n\n\n\n
\n );\n }\n}\n\nexport default TemperatureControl\n","import React from 'react';\n\nclass Cook extends React.Component {\n constructor(props) {\n super(props);\n this.updateMode = this.updateMode.bind(this);\n this.addMode = this.addMode.bind(this);\n this.updatePreset = this.updatePreset.bind(this);\n this.addPreset = this.addPreset.bind(this);\n }\n\n updateMode(event){\n const id = event.target.id.split('_')\n const mode_id = id[1]\n var temp_supportedCookingModes = this.props.attributes.supportedCookingModes\n\n if (event.target.value === 'delete'){\n temp_supportedCookingModes.splice(mode_id, 1)\n } else if (event.target.value !== 'select') {\n temp_supportedCookingModes[mode_id] = event.target.value;\n }\n\n this.props.update('attributes/supportedCookingModes', temp_supportedCookingModes);\n }\n\n addMode(){\n var temp_supportedCookingModes = this.props.attributes.supportedCookingModes\n temp_supportedCookingModes.push(\"\");\n this.props.update('attributes/supportedCookingModes', temp_supportedCookingModes);\n }\n\n updatePreset(event){\n const id = event.target.id.split('_')\n const preset_id = id[1]\n var temp_foodPresets = this.props.attributes.foodPresets\n\n if(id[0] === 'lang'){\n temp_foodPresets[preset_id].food_synonyms[0].lang = event.target.value;\n } else if (id[0] === 'names'){\n temp_foodPresets[preset_id].food_synonyms[0].synonym = event.target.value.split(',');\n temp_foodPresets[preset_id].food_preset_name = event.target.value.split(',')[0]\n } else if (id[0] === 'units'){\n temp_foodPresets[preset_id].supported_units[0] = event.target.value;\n }\n this.props.update('attributes/foodPresets', temp_foodPresets);\n }\n\n addPreset(){\n var temp_foodPresets = this.props.attributes.foodPresets\n temp_foodPresets.push({\n \"food_preset_name\": \"\",\n \"supported_units\": [\"\"],\n \"food_synonyms\": [{\n \"synonym\": [\"\"],\n \"language\": \"en\"\n }]\n });\n this.props.update('attributes/foodPresets', temp_foodPresets);\n }\n\n render() {\n\n const names_box = {\n width: '150px'\n }\n\n const modes = this.props.attributes.supportedCookingModes.map((mode, i) => {\n\n return (\n \n
\n
\n
\n
\n \n Mode: \n \n Select a mode \n Delete this mode \n UNKNOWN_COOKING_MODE \n BAKE \n BEAT \n BLEND \n BOIL \n BREW \n BROIL \n CONVECTION_BAKE \n COOK \n DEFROST \n DEHYDRATE \n FERMENT \n FRY \n KNEAD \n MICROWAVE \n PRESSURE_COOK \n PUREE \n ROAST \n SAUTE \n SLOW_COOK \n SOUS_VIDE \n STEAM \n STEW \n WARM \n WHIP \n \n \n
\n
\n
\n\n )\n });\n\n const presets = this.props.attributes.foodPresets.map((preset, i) => {\n\n return (\n \n
\n
\n
\n
\n \n Language: \n \n es \n en \n \n \n \n Preset name: \n \n \n \n Units: \n \n No units \n Unkown \n Centimeters \n Cups \n Deciliters \n Feet \n Fluid ounces \n Gallons \n Grams \n Inches \n Kilograms \n Liters \n Meters \n Miligrams \n Mililiters \n Milimeters \n Ounces \n Pinch \n Pints \n Portion \n Pounds \n Quarts \n Tablespoons \n Teaspoons \n \n \n
\n
\n
\n )\n });\n\n return (\n \n\n
\n
\n Add a cooking mode\n
\n
\n Add \n
\n
\n\n {modes}\n\n
\n
\n Add a preset\n
\n
\n Add \n
\n
\n\n {presets}\n\n
\n );\n }\n}\n\nexport default Cook\n","import React from 'react';\n\nclass SensorState extends React.Component {\n constructor(props) {\n super(props);\n this.update = this.update.bind(this);\n }\n\n update(event){\n const value = event.target.value;\n var sensor = {\n name: value\n }\n\n switch (value) {\n default:\n sensor['descriptiveCapabilities'] = {\n availableStates: ['fair','good','healthy','moderate','poor','severe','unhealthy','unhealthy for sensitive groups','very poor','very unhealthy','unknown'],\n }\n sensor['numericCapabilities']= { rawValueUnit: \"AQI\" }\n break;\n case 'AirQuality':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['fair','good','healthy','moderate','poor','severe','unhealthy','unhealthy for sensitive groups','very poor','very unhealthy','unknown'],\n }\n sensor['numericCapabilities']= { rawValueUnit: \"AQI\" }\n break;\n case 'CarbonDioxideLevel':\n sensor['descriptiveCapabilities'] = {\n numericCapabilities: { rawValueUnit: \"PARTS_PER_MILLION\" }\n }\n break;\n case 'CarbonMonoxideLevel':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['carbon monoxide detected','high','no carbon monoxide detected','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n case 'FilterCleanliness':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['clean','dirty','needs replacement','unknown']\n }\n break;\n case 'FilterLifeTime':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['good','new','replace soon','replace now','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'HEPAFilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'Max2FilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'PM2.5':\n sensor['numericCapabilities']= { rawValueUnit: \"MICROGRAMS_PER_CUBIC_METER\" }\n break;\n case 'PM10':\n sensor['numericCapabilities']= { rawValueUnit: \"MICROGRAMS_PER_CUBIC_METER\" }\n break;\n case 'PreFilterLifeTime':\n sensor['numericCapabilities']= { rawValueUnit: \"PERCENTAGE\" }\n break;\n case 'SmokeLevel':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['smoke detected','high','no smoke detected','unknown']\n }\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n case 'WaterLeak':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['leak','no leak','unknown']\n }\n break;\n case 'RainDetection':\n sensor['descriptiveCapabilities'] = {\n availableStates: ['rain detected','no rain detected','unknown']\n }\n break;\n case 'VolatileOrganicCompounds':\n sensor['numericCapabilities']= { rawValueUnit: \"PARTS_PER_MILLION\" }\n break;\n }\n\n var sensorStatesSupported = []\n sensorStatesSupported.push(sensor);\n this.props.update('attributes/' + event.target.id,sensorStatesSupported);\n }\n\n render() {\n return (\n \n
\n
\n Sensor type\n
\n
\n \n Select \n Air Quality \n Carbon Dioxide Level \n Carbon Monoxide Level \n Filter Clean liness \n Filter Life Time \n HEPA Filter Life Time \n Max2 Filter Life Time \n PM2.5 \n PM10 \n PreFilter Life Time \n Smoke Level \n Water Leak \n Rain Detection \n Volatile Organic Compounds \n \n
\n
\n \n
\n
\n\n
\n );\n }\n}\n\nexport default SensorState\n","import React from 'react';\nimport Switch from \"react-switch\";\nimport Text from '../editor/Text'\nimport Scene from '../editor/traits/Scene'\nimport OnOff from '../editor/traits/OnOff'\nimport Brightness from '../editor/traits/Brightness'\nimport FanSpeed from '../editor/traits/FanSpeed'\nimport ColorSetting from '../editor/traits/ColorSetting'\nimport TemperatureSetting from '../editor/traits/TemperatureSetting'\nimport Toggles from '../editor/traits/Toggles'\nimport Modes from '../editor/traits/Modes'\nimport HumiditySetting from '../editor/traits/HumiditySetting'\nimport OpenClose from '../editor/traits/OpenClose'\nimport Rotation from '../editor/traits/Rotation'\nimport Fill from '../editor/traits/Fill'\nimport ArmDisarm from '../editor/traits/ArmDisarm'\nimport StartStop from '../editor/traits/StartStop'\nimport Timer from '../editor/traits/Timer'\nimport TemperatureControl from '../editor/traits/TemperatureControl'\nimport Cook from '../editor/traits/Cook'\nimport SensorState from '../editor/traits/SensorState'\nimport getCookieValue from '../../functions'\nimport { root, deviceReference } from '../../constants'\n\nimport './Editor.css';\n\nclass Editor extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n var create = false;\n if (id === \"\") create = true;\n this.state = {\n id: id,\n create: create,\n device: {\n attributes: {},\n deviceInfo: {},\n id: \"\",\n name: {\n defaultNames: [],\n nicknames: [],\n name: \"\"\n },\n traits: [],\n type: \"\"\n },\n status: {\n online: true\n },\n posible_traits: [],\n save_status: \"\"\n }\n this.updateNames = this.updateNames.bind(this);\n this.update = this.update.bind(this);\n this.updateId = this.updateId.bind(this);\n this.updateType = this.updateType.bind(this);\n this.updateTraits = this.updateTraits.bind(this);\n this.save = this.save.bind(this);\n this.delete = this.delete.bind(this);\n this.renderAttrinutes = this.renderAttrinutes.bind(this);\n }\n\n componentDidMount() {\n if (!this.state.create){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n device: data,\n posible_traits: deviceReference.devices[data.type].traits\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n }\n\n updateNames(dumy_key, value){\n var names = value.split(',');\n var temp_device = this.state.device\n temp_device.name = {\n defaultNames: names,\n nicknames: names,\n name: names[0]\n }\n this.setState({\n device: temp_device\n })\n }\n\n update(key, value){\n var temp_device = this.state.device\n var keys = key.split('/');\n if (keys.length === 1)\n temp_device[key] = value\n else if (keys.length === 2)\n temp_device[keys[0]][keys[1]] = value\n else if (keys.length === 3)\n temp_device[keys[0]][keys[1]][keys[2]] = value\n this.setState({\n device: temp_device\n })\n }\n\n updateId(event){\n this.update('id',event.target.value)\n }\n\n updateType(event){\n this.update('type',event.target.value)\n this.setState({\n posible_traits: deviceReference.devices[event.target.value].traits\n });\n }\n\n updateTraits(checked, trait){\n var temp_device = this.state.device\n var temp_status = this.state.status\n if (checked) {\n if (this.state.device.traits.includes(trait) === false){\n //Push the trait to the device\n temp_device.traits.push(trait)\n //Set the default values\n var attributes = deviceReference.traits[trait].attributes;\n Object.keys(attributes).forEach((attribute, i) => {\n temp_device.attributes[attribute] = attributes[attribute].default\n });\n //Set the default status params\n var params = deviceReference.traits[trait].params;\n params.forEach((param, i) => {\n temp_status[param] = deviceReference.params[param].default\n });\n }\n } else {\n if (this.state.device.traits.includes(trait) === true){\n temp_device.traits = temp_device.traits.filter(function(value, index, arr){ return value !== trait;});\n }\n }\n this.setState({\n device: temp_device,\n status: temp_status\n })\n }\n\n save(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n JSON.parse(http.responseText);\n this.setState({\n save_status: \"Saved correctly.\"\n });\n if (this.state.create) {\n window.location.href = '/devices'\n }\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the changes haven't been saved.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n var payload = {\n \"device\": this.state.device\n }\n if (this.state.create){\n http.open(\"POST\", root + \"api/devices/create/\");\n payload.status = this.state.status\n } else {\n http.open(\"POST\", root + \"api/devices/update/\");\n }\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify(payload));\n }\n\n delete(){\n if(window.confirm('Do you want to delete the device?')){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n window.location.href = \"/devices/\"\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the device hasn't been deleted.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/devices/delete/\" + this.state.device.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n } else {\n this.setState({\n save_status: \"Ok. The device is save.\"\n });\n }\n }\n\n renderAttrinutes(trait){\n if (this.state.device.traits.includes(trait)){\n if (trait === 'action.devices.traits.Scene')\n return \n else if (trait === 'action.devices.traits.OnOff')\n return \n else if (trait === 'action.devices.traits.Brightness')\n return \n else if (trait === 'action.devices.traits.ColorSetting')\n return \n else if (trait === 'action.devices.traits.FanSpeed')\n return \n else if (trait === 'action.devices.traits.TemperatureSetting')\n return \n else if (trait === 'action.devices.traits.Toggles')\n return \n else if (trait === 'action.devices.traits.Modes')\n return \n else if (trait === 'action.devices.traits.HumiditySetting')\n return \n else if (trait === 'action.devices.traits.OpenClose')\n return \n else if (trait === 'action.devices.traits.Rotation')\n return \n else if (trait === 'action.devices.traits.Fill')\n return \n else if (trait === 'action.devices.traits.ArmDisarm')\n return \n else if (trait === 'action.devices.traits.StartStop')\n return \n else if (trait === 'action.devices.traits.Timer')\n return \n else if (trait === 'action.devices.traits.TemperatureControl')\n return \n else if (trait === 'action.devices.traits.Cook')\n return \n else if (trait === 'action.devices.traits.SensorState')\n return \n }\n }\n\n render() {\n\n const deleteButton = {\n backgroundColor: 'red'\n }\n\n const deleteButtonDisabled = {\n backgroundColor: 'red',\n opacity: '0.2'\n }\n\n const types = Object.keys(deviceReference.devices).map((type) => {\n return {deviceReference.devices[type].name} \n })\n\n const nicknames = this.state.device.name.nicknames.map((name) => {\n return name\n });\n\n const traits = this.state.posible_traits.map((trait) =>\n \n
\n
\n
\n {deviceReference.traits[trait].name} \n
\n
\n {this.updateTraits(checked,trait)}} checked={this.state.device.traits.includes(trait)} />\n
\n
\n
\n {this.renderAttrinutes(trait)}\n
\n );\n\n return (\n \n\n
\n
Global settings \n
\n General settings of the device. \n
\n \n
\n
\n
\n Device ID*\n
\n
\n \n
\n
\n
\n
\n Device Type*\n
\n
\n \n Select a device \n {types}\n \n
\n
\n
\n \n \n \n \n \n Nick names must be separeted by , commas. \n * data is required. \n
\n \n Traits \n \n The traits define what the device can do. \n
\n {traits}\n \n \n Delete \n Save \n {this.state.save_status} \n
\n \n
\n\n
\n );\n }\n}\n\nexport default Editor\n","import React from 'react';\nimport ReactJson from 'react-json-view'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Editor extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n this.state = {\n id: id,\n device: {\n attributes: {},\n deviceInfo: {},\n id: \"\",\n name: {\n defaultnames: [],\n nicknames: [],\n name: \"\"\n },\n traits: [],\n type: \"\"\n },\n status: {\n online: true\n }\n }\n }\n\n componentDidMount() {\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n var data = JSON.parse(dev.responseText);\n this.setState({\n device: data\n });\n } else {\n console.error(dev.statusText);\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n\n var sta = new XMLHttpRequest();\n sta.onload = function (e) {\n if (sta.readyState === 4) {\n if (sta.status === 200) {\n var data = JSON.parse(sta.responseText);\n this.setState({\n status: data\n });\n } else {\n console.error(sta.statusText);\n }\n }\n }.bind(this);\n sta.open(\"GET\", root + \"api/status/get/\" + this.state.id + \"/\");\n sta.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n sta.send();\n }\n\n\n\n render() {\n\n const json_viewer = {\n textAlign: 'left',\n }\n\n return (\n \n\n
\n
Device definition \n
\n General settings of the device. \n
\n \n
\n \n
\n
\n\n
\n
Device status \n
\n Status of the device. \n
\n \n
\n \n
\n
\n\n
\n );\n }\n}\n\nexport default Editor\n","import React from 'react';\nimport ReactJson from 'react-json-view'\nimport getCookieValue from '../../functions'\nimport { root, deviceReference } from '../../constants'\n\nimport './Connecting.css';\n\nclass Connecting extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3]\n this.state = {\n id: id,\n traits: [],\n params: [],\n commands: []\n }\n }\n\n componentDidMount() {\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n const data = JSON.parse(dev.responseText);\n const traits = data.traits;\n var commands = [];\n var params = []\n traits.forEach((trait) => {\n params = params.concat(deviceReference.traits[trait].params);\n commands = commands.concat(deviceReference.traits[trait].commands);\n });\n this.setState({\n traits: traits,\n params: params,\n commands: commands\n });\n } else {\n console.error(dev.statusText)\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/devices/get/\" + this.state.id + \"/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n }\n\n render() {\n\n const params = this.state.params.map((param, i) => {\n var type = deviceReference.params[param].type\n if (type === 'list')\n type = 'string'\n\n var topic = 'None - Controlled only by the device'\n if (deviceReference.params[param].commanded)\n topic = 'device/' + this.state.id + '/' + param\n\n return (\n \n
{param}
\n
{topic}
\n
{type}
\n
\n )\n })\n\n const commands = this.state.commands.map((command, i) => {\n return (\n \n
{command.command}
\n
{'device/' + this.state.id + '/command'}
\n
{command.description}
\n
\n )\n })\n\n var example = {\"id\":\"light001\",\"param\":\"brightness\",\"value\":\"80\",\"intent\":\"execute\"}\n var advise = {\n textAlign: 'left'\n }\n\n return (\n \n\n
\n
Params \n
\n
Params are data interchanged between Google and the device and stored in Homeware database.
\n
If the param has got a notification topic, Google Home can control it. A notification will be sent in this MQTT topic when Google change a param.
\n
If the param hasn't got a notification topic, the device should update the param value when necessary.
\n
\n
\n
\n
Param
\n
Notifications topic
\n
Type
\n
\n {params}\n
\n
\n
The device can change the value of any param sending an execute request to device/control topic as follow
\n
\n \n
\n\n
\n
Commands \n
\n
Commands are directs orders from Google to the device. Commands are not stored in Homeware's database.
\n
\n
\n
\n
Command
\n
Notifications topic
\n
Description
\n
\n {commands}\n
\n\n
\n );\n }\n}\n\nexport default Connecting\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Tasks.css';\n\nclass Tasks extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n devices: [],\n tasks: []\n }\n this.loadData = this.loadData.bind(this);\n this.openManager = this.openManager.bind(this);\n this.newTask = this.newTask.bind(this);\n }\n\n componentDidMount() {\n this.loadData();\n }\n\n loadData(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n devices: data.devices,\n tasks: data.tasks\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/global/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n openManager(event){\n window.location.href = '/tasks/manager/' + event.target.id.split('_')[1]\n }\n\n newTask(){\n window.location.href = '/tasks/manager/'\n }\n\n render() {\n\n const tasks = this.state.tasks.map((task, i) => {\n return(\n \n
{ task.title } \n
\n
{ task.description }
\n
\n )\n });\n\n return (\n \n
\n
Tasks \n \n\n
\n {tasks}\n
\n\n
\n New \n
\n
\n );\n }\n}\n\nexport default Tasks\n","import React from 'react';\nimport Triggers from './Triggers'\n\nimport '../pages/Manager.css';\n\nclass Logic extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n this.addOr = this.addOr.bind(this);\n this.addAnd = this.addAnd.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n addOr() {\n this.props.addTriggerLogic('or',this.props.id)\n }\n\n addAnd() {\n this.props.addTriggerLogic('and',this.props.id)\n }\n\n openTriggerAssistant() {\n this.props.openTriggerAssistant(this.props.id)\n }\n\n render() {\n\n const num_operations = this.props.triggers[this.props.id].operation.length-1;\n const operations = this.props.triggers[this.props.id].operation.map((op, i) => {\n return (\n \n \n {i < num_operations ? {this.props.triggers[this.props.id].type} : '' }\n
\n );\n });\n\n return (\n \n {operations}\n
\n Or \n And \n Trigger \n Delete \n
\n
\n );\n }\n}\n\nexport default Logic\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Trigger extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n this.renderTriggerText = this.renderTriggerText.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n renderTriggerText() {\n const week = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']\n const device_triggers = ['d2b','d2i','d2l','d2s']\n\n const type = this.props.triggers[this.props.id].type;\n const operation = this.props.triggers[this.props.id].operation.split(':');\n if (device_triggers.includes(type)) {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + operation[3];\n } else if (type === 'd2d') {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + this.props.devices[operation[3]] + ' (' + (deviceReference.params[operation[4]].name ? deviceReference.params[operation[4]].name : operation[4]) + ') ';\n } else if (type === 'd2c') {\n return this.props.devices[operation[0]] + ' (' + (deviceReference.params[operation[1]] ? deviceReference.params[operation[1]].name : operation[1]) + ') ' + operation[2] + ' ' + operation[3];\n } else if (type === 'time') {\n\n var days = '';\n for( var i = 0; i < operation[2].length; i++){\n days += week[operation[2][i]];\n if (i !== operation[2].length - 1)\n days += ', ';\n }\n return operation[0] + ':' + operation[1] + ' on ' + days\n\n } else {\n return this.props.triggers[this.props.id].operation\n }\n }\n\n render() {\n\n return (\n \n
{this.renderTriggerText()} \n
\n
\n );\n }\n}\n\nexport default Trigger\n","import React from 'react';\nimport Logic from './Logic'\nimport Trigger from './Trigger'\n\nclass Triggers extends React.Component {\n constructor(props) {\n super(props);\n this.addOr = this.addOr.bind(this);\n this.addAnd = this.addAnd.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n }\n\n addOr() {\n this.props.addTriggerLogic('or','triggers')\n }\n\n addAnd() {\n this.props.addTriggerLogic('and','triggers')\n }\n\n openTriggerAssistant() {\n this.props.openTriggerAssistant('triggers')\n }\n\n render() {\n\n if (this.props.triggers.trigger) {\n var operation = this.props.triggers[this.props.id]\n const device_triggers = ['d2b','d2d','d2i','d2l','time','d2c']\n\n if (operation.type === 'or'){\n return \n } else if (operation.type === 'and'){\n return \n } else if (device_triggers.includes(operation.type)){\n return \n }\n } else {\n return (\n \n Or \n And \n Trigger \n
\n );\n }\n\n }\n}\n\nexport default Triggers\n","import React from 'react';\n\nimport '../pages/Manager.css';\n\nclass Assistant extends React.Component {\n constructor(props) {\n super(props);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n }\n\n addTriggerOperation(){\n const hour = document.getElementById('hour').value;\n const minute = document.getElementById('minute').value;\n var week = '';\n\n if (document.getElementById('monday').checked)\n week += '1'\n if (document.getElementById('tuesday').checked)\n week += '2'\n if (document.getElementById('wednesday').checked)\n week += '3'\n if (document.getElementById('thursday').checked)\n week += '4'\n if (document.getElementById('friday').checked)\n week += '5'\n if (document.getElementById('saturday').checked)\n week += '6'\n if (document.getElementById('sunday').checked)\n week += '0'\n\n const value = hour + ':' + minute + ':' + week;\n this.props.addTriggerOperation('time',value);\n this.props.closeTriggerAssistant();\n }\n\n render() {\n\n return (\n \n
Triggered by time \n
\n
\n Hour*\n
\n
\n \n
\n
\n 24h format \n
\n
\n
\n
\n Minute*\n
\n
\n \n
\n
\n \n
\n
\n\n
\n
\n Week*\n
\n
\n Sunday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Monday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Tuesday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Wednesday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Thursday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Friday\n
\n
\n \n
\n
\n\n
\n
\n
\n
\n Saturday\n
\n
\n \n
\n
\n\n\n\n\n\n
\n Save \n Cancel \n
\n
\n );\n }\n}\n\nexport default Assistant\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Device extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device: \"\"\n }\n this.updateDevice = this.updateDevice.bind(this);\n this.updateParam = this.updateParam.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n this.typeConversion = this.typeConversion.bind(this);\n }\n\n updateDevice(event) {\n this.setState({\n device: event.target.value\n });\n }\n\n updateParam(event) {\n this.setState({\n param: event.target.value\n });\n }\n\n addTriggerOperation(){\n const device = document.getElementById('device').value;\n const param = document.getElementById('param').value;\n const comparator = document.getElementById('comparator').value;\n const value = document.getElementById('value').value;\n\n\n const operation = device + ':' + param + ':' + comparator + ':' + value;\n this.props.addTriggerOperation(this.typeConversion(deviceReference.params[this.state.param].type),operation);\n this.props.closeTriggerAssistant();\n }\n\n typeConversion(origen) {\n const type = {\n int: 'd2i',\n list: 'd2l',\n bool: 'd2b',\n string: 'd2s',\n color: 'd2c'\n }\n return type[origen]\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return {this.props.devices[device]} \n })\n\n const params = this.state.device === \"\" ? '' : Object.keys(this.props.status[this.state.device]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n var value = '';\n if (deviceReference.params[this.state.param]){\n const type = this.typeConversion(deviceReference.params[this.state.param].type);\n if(type === 'd2i'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2s'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2b' || type === 'd2l'){\n\n const options = deviceReference.params[this.state.param].select.map((option) => {\n return {option} \n })\n\n value = (\n \n
\n Value*\n
\n
\n \n {options}\n \n
\n
\n )\n }\n\n }\n\n return (\n \n
Triggered by a device \n\n
\n
\n Device*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param*\n
\n
\n \n Select a param \n {params}\n \n
\n
\n
\n
\n Comparator*\n
\n
\n \n = \n < \n > \n <= \n >= \n \n
\n
\n\n {value}\n\n
\n Save \n Cancel \n
\n
\n );\n }\n}\n\nexport default Device\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass DeviceToDevice extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device_a: \"\",\n device_b: \"\"\n }\n this.updateDependencies = this.updateDependencies.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n }\n\n updateDependencies(event) {\n var state = this.state;\n state[event.target.id] = event.target.value;\n this.setState(state);\n }\n\n\n addTriggerOperation(){\n const device_a = document.getElementById('device_a').value;\n const param_a = document.getElementById('param_a').value;\n const comparator = document.getElementById('comparator').value;\n const device_b = document.getElementById('device_b').value;\n const param_b = document.getElementById('param_b').value;\n\n const operation = device_a + ':' + param_a + ':' + comparator + ':' + device_b + ':' + param_b;\n this.props.addTriggerOperation('d2d',operation);\n this.props.closeTriggerAssistant();\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return {this.props.devices[device]} \n })\n\n const params_a = this.state.device_a === \"\" ? '' : Object.keys(this.props.status[this.state.device_a]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n const params_b = this.state.device_b === \"\" ? '' : Object.keys(this.props.status[this.state.device_b]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n return (\n \n
Compare two devices \n\n
\n
\n Device A*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param A*\n
\n
\n \n Select a param \n {params_a}\n \n
\n
\n\n
\n
\n Comparator*\n
\n
\n \n = \n < \n > \n <= \n >= \n \n
\n
\n\n
\n
\n Device B*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param B*\n
\n
\n \n Select a param \n {params_b}\n \n
\n
\n\n
\n Save \n Cancel \n
\n
\n );\n }\n}\n\nexport default DeviceToDevice\n","import React from 'react';\nimport Time from './Time'\nimport Device from './Device'\nimport DeviceToDevice from './DeviceToDevice'\n\nimport '../pages/Manager.css';\n\nclass Assistant extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n type: ''\n }\n this.timeTigger = this.timeTigger.bind(this);\n this.deiceTrigger = this.deiceTrigger.bind(this);\n this.deviceToDeviceTrigger = this.deviceToDeviceTrigger.bind(this);\n }\n\n timeTigger() {\n this.setState({\n type: 'time'\n });\n }\n\n deiceTrigger() {\n this.setState({\n type: 'device'\n });\n }\n\n deviceToDeviceTrigger() {\n this.setState({\n type: 'device2device'\n });\n }\n\n render() {\n\n if (this.state.type === '')\n return (\n \n
Add a new trigger \n
\n Time \n Device \n Device to device \n Cancel \n
\n
\n );\n else if (this.state.type === 'time')\n return \n else if (this.state.type === 'device')\n return \n else if (this.state.type === 'device2device')\n return \n }\n}\n\nexport default Assistant\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Target extends React.Component {\n constructor(props) {\n super(props);\n this.delete = this.delete.bind(this);\n }\n\n delete() {\n this.props.delete(this.props.id);\n }\n\n render() {\n\n const container = {\n marginBottom: '10px'\n }\n\n return (\n \n
{ (this.props.devices[this.props.target.device] ? this.props.devices[this.props.target.device] : this.props.target.device)\n + ' (' + (deviceReference.params[this.props.target.param] ? deviceReference.params[this.props.target.param].name : this.props.target.param)\n + ') = ' + this.props.target.value} \n
\n
\n );\n }\n}\n\nexport default Target\n","import React from 'react';\nimport { deviceReference } from '../../constants'\n\nimport '../pages/Manager.css';\n\nclass Device extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n device: \"\"\n }\n this.updateDevice = this.updateDevice.bind(this);\n this.updateParam = this.updateParam.bind(this);\n this.addTarget = this.addTarget.bind(this);\n this.typeConversion = this.typeConversion.bind(this);\n }\n\n updateDevice(event) {\n this.setState({\n device: event.target.value\n });\n }\n\n updateParam(event) {\n this.setState({\n param: event.target.value\n });\n }\n\n addTarget(){\n const device = document.getElementById('device').value;\n const param = document.getElementById('param').value;\n const value = document.getElementById('value').value;\n\n const target = {\n device: device,\n param: param,\n value: value\n }\n this.props.addTarget(target);\n document.getElementById('device').value = '';\n document.getElementById('param').value = '';\n this.setState({\n param: ''\n });\n }\n\n typeConversion(origen) {\n const type = {\n int: 'd2i',\n list: 'd2l',\n bool: 'd2b',\n string: 'd2s',\n color: 'd2c'\n }\n return type[origen]\n }\n\n render() {\n\n const devices = Object.keys(this.props.devices).map((device) => {\n return {this.props.devices[device]} \n })\n\n const params = this.state.device === \"\" ? '' : Object.keys(this.props.status[this.state.device]).map((param) => {\n return { deviceReference.params[param] ? deviceReference.params[param].name : param + ' - Not supported yet' } \n })\n\n var value = '';\n if (deviceReference.params[this.state.param]){\n const type = this.typeConversion(deviceReference.params[this.state.param].type);\n if(type === 'd2i'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2s'){\n value = (\n \n
\n Value*\n
\n
\n \n
\n
\n )\n } else if(type === 'd2b' || type === 'd2l'){\n\n const options = deviceReference.params[this.state.param].select.map((option) => {\n return {option} \n })\n\n value = (\n \n
\n Value*\n
\n
\n \n {options}\n \n
\n
\n )\n }\n\n }\n\n return (\n \n
New target \n\n
\n
\n Device*\n
\n
\n \n Select a device \n {devices}\n \n
\n
\n
\n
\n Param*\n
\n
\n \n Select a param \n {params}\n \n
\n
\n\n {value}\n\n
\n Add \n
\n
\n );\n }\n}\n\nexport default Device\n","import React from 'react';\nimport Triggers from '../manager/Triggers.js'\nimport Assistant from '../manager/Assistant.js'\nimport Target from '../manager/Target.js'\nimport DeviceTarget from '../manager/DeviceTarget.js'\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nimport './Manager.css';\n\nclass Manager extends React.Component {\n constructor(props) {\n super(props);\n const id = window.location.pathname.split('/')[3];\n var create = false;\n if (id === \"\") create = true;\n this.state = {\n id: id,\n create: create,\n save_status: \"\",\n trigger_assistant_parent: 0,\n task: {\n title: '',\n description: '',\n triggers: {},\n target: []\n },\n devices: [],\n status: {}\n }\n this.update = this.update.bind(this);\n this.save = this.save.bind(this);\n this.delete = this.delete.bind(this);\n this.deleteTrigger = this.deleteTrigger.bind(this);\n this.addTriggerLogic = this.addTriggerLogic.bind(this);\n this.openTriggerAssistant = this.openTriggerAssistant.bind(this);\n this.addTriggerOperation = this.addTriggerOperation.bind(this);\n this.closeTriggerAssistant = this.closeTriggerAssistant.bind(this);\n this.addTarget = this.addTarget.bind(this);\n }\n\n componentDidMount() {\n // Load devices data\n var dev = new XMLHttpRequest();\n dev.onload = function (e) {\n if (dev.readyState === 4) {\n if (dev.status === 200) {\n var data = JSON.parse(dev.responseText);\n var devices_names = {}\n data.devices.forEach((device) => {\n devices_names[device.id] = device.name.name\n })\n this.setState({\n devices: devices_names,\n status: data.status\n });\n } else {\n console.error(dev.statusText);\n }\n }\n }.bind(this);\n dev.open(\"GET\", root + \"api/global/get/\");\n dev.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n dev.send();\n\n // Load task if neeeded\n if (!this.state.create){\n var tas = new XMLHttpRequest();\n tas.onload = function (e) {\n if (tas.readyState === 4) {\n if (tas.status === 200) {\n var data = JSON.parse(tas.responseText);\n console.log(data);\n this.setState({\n task: data\n });\n } else {\n console.error(tas.statusText);\n }\n }\n }.bind(this);\n tas.open(\"GET\", root + \"api/tasks/get/\" + this.state.id + \"/\");\n tas.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n tas.send();\n }\n }\n\n update(event){\n var task = this.state.task;\n task[event.target.id] = event.target.value\n this.setState({\n task: task\n })\n }\n\n save(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n JSON.parse(http.responseText);\n if (this.state.create){\n window.location.href = \"/tasks\"\n } else {\n this.setState({\n save_status: \"Saved correctly.\"\n });\n }\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the changes haven't been saved.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n var payload = {\n \"task\": this.state.task\n }\n if (this.state.create){\n http.open(\"POST\", root + \"api/tasks/create/\");\n } else {\n http.open(\"POST\", root + \"api/tasks/update/\");\n payload['id'] = this.state.id;\n }\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify(payload));\n }\n\n delete(){\n if(window.confirm('Do you want to delete the task?')){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n window.location.href = \"/tasks/\"\n } else {\n console.error(http.statusText);\n this.setState({\n save_status: \"Error, the device hasn't been deleted.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/tasks/delete/\" + this.state.id + \"/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n } else {\n this.setState({\n save_status: \"Ok. The device is save.\"\n });\n }\n }\n\n deleteTrigger(id) {\n // Get the task\n var task = this.state.task;\n var triggers = task.triggers;\n // Get the the parent id\n const parent = triggers[id].parent\n if (parent !== 'triggers') {\n // Delete from the parent\n const index = triggers[parent].operation.indexOf(id);\n triggers[parent].operation.splice(index,1)\n // Delete the trigger\n delete triggers[id];\n task.triggers = triggers;\n } else {\n task.triggers = {};\n }\n this.setState({\n task: task\n });\n }\n\n addTriggerLogic(type, parent) {\n // Get the triggers\n var task = this.state.task;\n if (parent !== 'triggers') {\n // Get the timestamp\n const ts = Date.now();\n // Compose and create the logic trigger\n task.triggers[ts] = {\n operation: [],\n parent: parent,\n type: type\n };\n // Register the trigger in the parent\n task.triggers[parent].operation.push(ts);\n } else {\n task.triggers['trigger'] = {\n operation: [],\n parent: 'triggers',\n type: type\n };\n }\n // Update the component state\n this.setState({\n task: task\n });\n }\n\n openTriggerAssistant(parent) {\n this.setState({\n trigger_assistant_parent: parent\n });\n }\n\n addTriggerOperation(type, operation) {\n // Get the triggers\n var task = this.state.task;\n const parent = this.state.trigger_assistant_parent;\n if (parent !== 'triggers') {\n // Get the timestamp\n const ts = Date.now();\n // Compose and create the logic trigger\n task.triggers[ts] = {\n operation: operation,\n parent: parent,\n type: type\n };\n // Register the trigger in the parent\n task.triggers[parent].operation.push(ts);\n } else {\n task.triggers['trigger'] = {\n operation: operation,\n parent: 'triggers',\n type: type\n };\n }\n // Update the component state\n this.setState({\n task: task\n });\n }\n\n closeTriggerAssistant() {\n this.setState({\n trigger_assistant_parent: 0\n });\n }\n\n addTarget(target) {\n var task = this.state.task;\n task.target.push(target);\n this.setState({\n task: task\n });\n }\n\n render() {\n\n const button = {\n width: '200px'\n }\n\n const deleteButton = {\n backgroundColor: 'red'\n }\n\n const deleteButtonDisabled = {\n backgroundColor: 'red',\n opacity: '0.2'\n }\n\n const separator = {\n width: '70%'\n }\n\n const targets = this.state.task.target.map((target, i) => {\n return \n })\n\n return (\n \n
Task \n
\n
\n
\n
\n Name*\n
\n
\n \n
\n
\n
\n
\n Description*\n
\n
\n \n
\n
\n
\n
Triggers \n
\n \n
\n {\n this.state.trigger_assistant_parent !== 0\n ?\n
\n :\n \n }\n \n Targets \n \n \n
\n {targets}\n \n\n \n \n Delete \n Save \n {this.state.save_status} \n
\n \n
\n );\n }\n}\n\nexport default Manager\n","import React from 'react';\nimport Switch from \"react-switch\";\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Settings extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n settings: {\n google: {},\n ddns: {},\n mqtt: {},\n apikey: \"\"\n },\n save_status: \"\",\n url: {\n auth: \"\",\n token: \"\",\n fulfillment: \"\"\n }\n }\n this.update = this.update.bind(this);\n this.enableDdnsProvider = this.enableDdnsProvider.bind(this);\n this.save = this.save.bind(this);\n }\n\n componentDidMount() {\n if (!this.state.create){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({\n settings: data,\n url: {\n auth: \"https://\" + data.ddns.hostname + \"/auth/\",\n token: \"https://\" + data.ddns.hostname + \"/token/\",\n fulfillment: \"https://\" + data.ddns.hostname + \"/smarthome/\"\n }\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/settings/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n }\n\n update(event){\n // this.props.update('attributes/' + event.target.id,event.target.value);\n const id = event.target.id.split(\"/\");\n var settings = this.state.settings;\n if (id.length === 1){\n settings[id[0]] = event.target.value;\n } else if (id.length === 2){\n settings[id[0]][id[1]] = event.target.value;\n }\n this.setState({\n settings: settings\n });\n }\n\n enableDdnsProvider(checked){\n var settings = this.state.settings;\n settings.ddns.enabled = checked;\n this.setState({\n settings: settings\n });\n }\n\n save(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n JSON.parse(http.responseText);\n this.setState({\n save_status: \"Saved correctly.\"\n });\n } else {\n this.setState({\n save_status: \"Error, the changes haven't been saved.\"\n });\n }\n setTimeout(function(){\n this.setState({\n save_status: \"\"\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"POST\", root + \"api/settings/update/\");\n http.setRequestHeader(\"Content-Type\", \"application/json;charset=UTF-8\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send(JSON.stringify(this.state.settings));\n }\n\n render() {\n\n return (\n \n
\n
Actions on Google \n
\n
\n
\n
\n Client ID\n
\n
\n \n
\n
\n
\n
\n Client Secret\n
\n
\n \n
\n
\n
\n
\n Authorization URL\n
\n
\n \n
\n
\n
\n
\n Token URL\n
\n
\n \n
\n
\n
\n
\n Fulfillment URL\n
\n
\n \n
\n
\n
\n
\n Save \n {this.state.save_status} \n
\n
\n Actions on Google settings. It is used to authenticate with Google. If you change it here, you must change it on the Actions Console > Develop > Account Linking. \n
\n
\n\n\n
\n
MQTT \n
\n
\n
\n
\n
\n Password\n
\n
\n \n
\n
\n
\n
\n Save \n {this.state.save_status} \n
\n
\n Important. You must configure the username and password into Mosquitto manually from a terminal. This is only for telling Homeware its credentials. Clear both if you don't use credentials. \n
\n
\n\n
\n
DDNS provider \n
\n
\n
\n
\n Status:\n
\n
\n { this.state.settings.ddns.status }\n
\n
\n
\n
\n IP and time:\n
\n
\n { this.state.settings.ddns.ip + \" updated at \" + this.state.settings.ddns.last}\n
\n
\n
\n
\n
\n
\n
\n Enable\n
\n
\n \n
\n
\n
\n
\n Provider\n
\n
\n \n Noip \n \n
\n
\n
\n
\n Username\n
\n
\n \n
\n
\n
\n
\n Password\n
\n
\n \n
\n
\n
\n
\n Hostname\n
\n
\n \n
\n
\n
\n
\n Save \n {this.state.save_status} \n
\n
\n Set up the access data to the DDNS provider account. Open an issue on Github if you want a DDNS provider that is not listed. \n
\n
\n\n\n
\n );\n }\n}\n\nexport default Settings\n","import React from 'react';\n\nfunction Component(props) {\n\n const component = {\n marginTop: '5px',\n width: '100%',\n display: 'grid',\n gridTemplateColumns: '70% 30%'\n }\n\n const textContainer = {\n textAlign: 'left',\n paddingTop: '4px'\n }\n\n const labelContainer = {\n textAlign: 'right',\n paddingTop: '4px'\n }\n\n const text = {\n fontSize: '18px'\n }\n\n const running = {\n fontSize: '12px',\n fontWeight: 'bold',\n color: 'white',\n backgroundColor: 'green',\n padding: '5px',\n paddingLeft: '10px',\n paddingRight: '10px',\n borderRadius: '5px'\n }\n\n const stopped = {\n fontSize: '12px',\n fontWeight: 'bold',\n color: 'white',\n backgroundColor: 'red',\n padding: '5px',\n paddingLeft: '10px',\n paddingRight: '10px',\n borderRadius: '5px'\n }\n\n return (\n \n
\n { props.title } \n
\n
\n { props.status } \n
\n
\n );\n}\n\nexport default Component\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\nimport Component from '../system/Component.js'\nconst ReactMarkdown = require('react-markdown')\n\n\nclass System extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n components: [],\n git: {\n version: '',\n description: '',\n code: 0\n },\n version: '',\n upgrading: false,\n show_system_message: false,\n system_message: ''\n }\n\n this.loadComponents = this.loadComponents.bind(this);\n this.upgrade = this.upgrade.bind(this);\n this.areYouAwake = this.areYouAwake.bind(this);\n this.restart = this.restart.bind(this);\n this.reboot = this.reboot.bind(this);\n this.shutdown = this.shutdown.bind(this);\n }\n\n componentDidMount() {\n\n this.loadComponents();\n setInterval(this.loadComponents,3000)\n\n var vers = new XMLHttpRequest();\n vers.onload = function (e) {\n if (vers.readyState === 4) {\n if (vers.status === 200) {\n var version = JSON.parse(vers.responseText);\n this.setState({ version: version.version });\n } else {\n console.error(vers.statusText);\n }\n }\n }.bind(this);\n vers.open(\"GET\", root + \"api/global/version/\");\n vers.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n vers.send();\n\n var git = new XMLHttpRequest();\n git.onload = function (e) {\n if (git.readyState === 4) {\n if (git.status === 200) {\n const latestRelease = JSON.parse(git.responseText);\n const description = latestRelease.body\n this.setState({ git: {\n version: latestRelease.tag_name,\n description: description,\n code: 200\n }\n });\n } else if (git.status === 403) {\n this.setState({ git: {\n version: 'GitHub rate limit exceeded. You have reloaded so many times. It will reset after some time.',\n code: 403\n }\n });\n } else {\n console.error(git.statusText);\n }\n }\n }.bind(this);\n git.open(\"GET\", 'https://api.github.com/repos/kikeelectronico/Homeware-LAN/releases/latest');\n git.send();\n }\n\n loadComponents() {\n var comp = new XMLHttpRequest();\n comp.onload = function (e) {\n if (comp.readyState === 4) {\n if (comp.status === 200) {\n var response = JSON.parse(comp.responseText);\n var components = []\n var keys = Object.keys(response);\n for (var i = 0; i < keys.length; i++) {\n components.push(response[keys[i]])\n }\n\n this.setState({ components: components });\n } else {\n console.error(comp.statusText);\n }\n }\n }.bind(this);\n comp.open(\"GET\", root + \"api/system/status/\");\n comp.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n comp.send();\n }\n\n upgrade(){\n if(window.confirm('Are you sure?')){\n window.open(root + \"files/buckup/homeware/\" + getCookieValue('token'))\n this.setState({\n show_system_message: true,\n system_message: 'Upgrading the system. It will take a couple of minutes and then you will be redirected to the home page.'\n });\n window.setTimeout(function() {\n var upg = new XMLHttpRequest();\n upg.onload = function (e) {\n if (upg.readyState === 4) {\n setInterval(this.areYouAwake,2000);\n }\n }.bind(this)\n upg.open(\"GET\", root + \"api/system/upgrade/\");\n upg.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n upg.send();\n }.bind(this),2000);\n }\n }\n\n areYouAwake(){\n var awa = new XMLHttpRequest();\n awa.onload = function (e) {\n if (awa.readyState === 4) {\n if (awa.status === 200) {\n window.location.href = '/'\n } else {\n console.error(awa.statusText);\n }\n }\n }.bind(this)\n awa.open(\"GET\", root + \"test/\");\n awa.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n awa.send();\n }\n\n restart(){\n this.setState({\n show_system_message: true,\n system_message: 'Restarting Homeware. It will take a couple of minutes and then you will be redirected to the home page.'\n });\n var res = new XMLHttpRequest();\n res.onload = function (e) {\n if (res.readyState === 4) {\n setInterval(this.areYouAwake,2000);\n }\n }.bind(this)\n res.open(\"GET\", root + \"api/system/restart\");\n res.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n res.send();\n }\n\n reboot(){\n this.setState({\n show_system_message: true,\n system_message: 'Rebooting the system. It will take a couple of minutes and then you will be redirected to the home page.'\n });\n var reb = new XMLHttpRequest();\n reb.onload = function (e) {\n if (reb.readyState === 4) {\n setInterval(this.areYouAwake,2000);\n }\n }.bind(this)\n reb.open(\"GET\", root + \"api/system/reboot\");\n reb.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n reb.send();\n }\n\n shutdown(){\n this.setState({\n show_system_message: true,\n system_message: 'The system will be shut down, you will lose the connection with Homeware.'\n });\n var shu = new XMLHttpRequest();\n shu.open(\"GET\", root + \"api/system/shutdown\");\n shu.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n shu.send();\n }\n\n render() {\n\n const upgrade_button = {\n width: '200px'\n }\n\n const git_description = {\n marginTop: '20px',\n marginLeft: '10%',\n width: '80%',\n paddingLeft: '20px',\n paddingRight: '20px',\n paddingTop: '20px',\n paddingBottom: '20px',\n borderRadius: '20px',\n border: '1px solid #aaa',\n textAlign: 'left'\n }\n\n const red_text = {\n color: 'red'\n }\n\n const components = this.state.components.map((component) =>\n \n );\n\n return (\n \n {\n this.state.show_system_message\n ?\n
\n
System message \n
\n
\n { this.state.system_message }\n
\n
\n :\n
\n
\n
System status \n
\n
\n { components }\n
\n
\n These are the core elements of Homeware-LAN. All must be running. \n
\n
\n\n
\n
Version \n
\n
\n
System version: { this.state.version }\n {\n this.state.version !== this.state.git.version\n ?\n
\n
New version: { this.state.git.version}\n
\n \n Upgrade \n
\n
\n :\n ' - The system is up to date.'\n }\n\n
\n
\n Verify if there is any code update and upgrade if necessary. \n
\n
\n\n
\n
Power \n
\n
\n Restart Homeware \n Reboot System \n Shutdown System \n
\n
\n Control the device and restart the Homeware-LAN installation. \n
\n
\n
\n }\n\n
\n );\n }\n}\n\nexport default System\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Backup extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n }\n }\n\n backup(){\n window.location = root + \"files/buckup/homeware/\" + getCookieValue('token')\n }\n\n render() {\n\n const button = {\n width: '200px'\n }\n\n const restore_url = root + \"files/restore/file/\" + getCookieValue('token') + \"/\";\n\n return (\n \n\n\n
\n
Backup \n
\n
\n Backup \n
\n
\n Download a backup file. \n
\n
\n\n
\n
Restore \n
\n
\n \n
\n
\n Restore a backup file. \n
\n
\n\n\n
\n );\n }\n}\n\nexport default Backup\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Access extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: {\n apikey: ''\n }\n }\n }\n\n componentDidMount() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({ data: data });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/access/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n generateAPIKey(){\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n // var data = JSON.parse(http.responseText);\n window.location.href = \"/access\"\n } else {\n console.error(http.statusText);\n }\n }\n };\n http.open(\"GET\", root + \"api/settings/apikey/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n render() {\n\n return (\n \n
\n
API key \n
\n
\n
\n
\n API Key\n
\n
\n \n
\n
\n
\n
\n Generate \n\n
\n
\n The API Key gives you access to the Homeware's API. Please do not generate an API Key if you are not sure of what you are doing. \n
\n
\n
\n );\n }\n}\n\nexport default Access\n","import React from 'react';\nimport getCookieValue from '../../functions'\nimport { root } from '../../constants'\n\nclass Logs extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n data: [],\n page: 1\n }\n\n this.previousPage = this.previousPage.bind(this);\n this.nextPage = this.nextPage.bind(this);\n this.downloadLog = this.downloadLog.bind(this);\n }\n\n componentDidMount() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n this.setState({ data: data });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/log/get/\");\n http.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n http.send();\n }\n\n previousPage() {\n if (this.state.page > 1)\n this.setState({ page: this.state.page - 1 });\n }\n\n nextPage() {\n if (this.state.page < this.state.data.length/10-1)\n this.setState({ page: this.state.page + 1 });\n }\n\n downloadLog() {\n window.location = root + \"files/log/homeware/\" + getCookieValue('token')\n }\n\n render() {\n\n const line = {\n width: '80%',\n marginLeft: '8%',\n marginTop: '10px',\n borderBottom: '1px solid #eee',\n paddingLeft: '20px',\n paddingBottom: '10px',\n paddingRight: '20px',\n textAlign: 'left'\n }\n\n const yellow = {\n color: 'orange'\n }\n\n const red = {\n color: 'red'\n }\n\n const homeware_lan_log_data = this.state.data.reverse().slice(0, this.state.page * 10);\n const homeware_lan_log = homeware_lan_log_data.map((register, i) =>\n \n { register.severity === 'Log' ? { register.severity } : '' }\n { register.severity === 'Warning' ? { register.severity } : '' }\n { register.severity === 'Alert' ? { register.severity } : '' }\n - { register.time } \n { register.message }\n
\n );\n\n return (\n \n
\n
Homeware-LAN log \n
\n
\n { homeware_lan_log }\n
\n
\n Load more \n Download \n
\n
\n
\n );\n }\n}\n\nexport default Logs\n","import React from 'react';\nimport { root } from '../../constants'\n\nclass Login extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n enable_message: false,\n message: ''\n }\n this.login = this.login.bind(this);\n this.grantAccess = this.grantAccess.bind(this);\n }\n\n login() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n var response = JSON.parse(http.responseText);\n if(response['status'] === 'in'){\n document.cookie = \"user=\" + response['user'] + \"; path=/\";\n document.cookie = \"token=\" + response['token'] + \"; path=/\";\n window.location = '/';\n } else if (response['status'] === 'fail'){\n this.setState({\n enable_message: true,\n message: 'Incorrect User or Password'\n })\n setTimeout(function(){\n this.setState({\n enable_message: false\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/user/login/\");\n http.setRequestHeader('user', document.getElementById('user').value)\n http.setRequestHeader('pass', document.getElementById('password').value)\n http.send();\n }\n\n grantAccess() {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.responseText !== 'fail')\n window.location = http.responseText;\n else {\n this.setState({\n enable_message: true,\n message: 'Incorrect User or Password'\n })\n setTimeout(function(){\n this.setState({\n enable_message: false\n });\n }.bind(this), 5000)\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/user/googleSync/\");\n http.setRequestHeader('user', document.getElementById('user').value)\n http.setRequestHeader('pass', document.getElementById('password').value)\n http.send();\n }\n\n render() {\n\n const form_container = {\n margin: '20%',\n }\n\n const element = {\n margin: '10px'\n }\n\n var message = '';\n if (this.state.enable_message){\n message = { this.state.message }
\n }\n\n return (\n \n { window.location.href.includes('google') ?
Google request access to Homeware-Lan
: '' }\n
\n
Username \n
\n
Password \n
\n
{ !window.location.href.includes('google') ? Login : Grant access } \n
\n { message }\n
\n );\n }\n}\n\nexport default Login\n","import React from 'react';\nimport './App.css';\nimport { BrowserRouter as Router, Route } from 'react-router-dom'\nimport getCookieValue from './functions'\nimport { root } from './constants'\n\nimport Menu from './components/web/Menu'\nimport Devices from './components/pages/Devices'\nimport Editor from './components/pages/Editor'\nimport Info from './components/pages/Info'\nimport Connecting from './components/pages/Connecting'\nimport Tasks from './components/pages/Tasks'\nimport Manager from './components/pages/Manager'\nimport Settings from './components/pages/Settings'\nimport System from './components/pages/System'\nimport Backup from './components/pages/Backup'\nimport Access from './components/pages/Access'\nimport Logs from './components/pages/Logs'\nimport Login from './components/pages/Login'\n\nclass App extends React.Component {\n constructor(props) {\n super(props);\n this.state = {\n session: false,\n version: ''\n }\n this.logout = this.logout.bind(this);\n this.menu = this.menu.bind(this);\n }\n\n componentDidMount() {\n if (!window.location.href.includes('assistant')) {\n var http = new XMLHttpRequest();\n http.onload = function (e) {\n if (http.readyState === 4) {\n if (http.status === 200) {\n var data = JSON.parse(http.responseText);\n if (data.status !== 'in' && !window.location.href.includes('login'))\n window.location.href = '/login/'\n else if (data.status === 'in')\n this.setState({\n session: true\n });\n } else {\n console.error(http.statusText);\n }\n }\n }.bind(this);\n http.open(\"GET\", root + \"api/user/validateToken/\");\n http.setRequestHeader('token', getCookieValue('token'))\n http.setRequestHeader('user', getCookieValue('user'))\n http.send();\n\n var vers = new XMLHttpRequest();\n vers.onload = function (e) {\n if (vers.readyState === 4) {\n if (vers.status === 200) {\n var version = JSON.parse(vers.responseText);\n this.setState({ version: version.version });\n } else {\n console.error(vers.statusText);\n }\n }\n }.bind(this);\n vers.open(\"GET\", root + \"api/global/version/\");\n vers.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))\n vers.send();\n }\n }\n\n logout() {\n document.cookie = \"user=; path=/\";\n document.cookie = \"token=; path=/\";\n this.setState({\n session: false\n });\n window.location.href = '/'\n }\n\n menu() {\n document.getElementById('menuIcon').classList.toggle(\"change_menu_icon\");\n document.getElementById('menu').classList.toggle(\"menu_show_up\");\n }\n\n render() {\n\n if (!this.state.session && !window.location.href.includes('login'))\n return ''\n else if (window.location.href.includes('login'))\n return (\n \n \n
\n );\n else\n return (\n \n \n
\n \n
\n
Homeware-LAN \n \n
\n
\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n \n );\n }\n}\n\nexport default App;\n","// This optional code is used to register a service worker.\n// register() is not called by default.\n\n// This lets the app load faster on subsequent visits in production, and gives\n// it offline capabilities. However, it also means that developers (and users)\n// will only see deployed updates on subsequent visits to a page, after all the\n// existing tabs open on the page have been closed, since previously cached\n// resources are updated in the background.\n\n// To learn more about the benefits of this model and instructions on how to\n// opt-in, read https://bit.ly/CRA-PWA\n\nconst isLocalhost = Boolean(\n window.location.hostname === 'localhost' ||\n // [::1] is the IPv6 localhost address.\n window.location.hostname === '[::1]' ||\n // 127.0.0.0/8 are considered localhost for IPv4.\n window.location.hostname.match(\n /^127(?:\\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/\n )\n);\n\nexport function register(config) {\n if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {\n // The URL constructor is available in all browsers that support SW.\n const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);\n if (publicUrl.origin !== window.location.origin) {\n // Our service worker won't work if PUBLIC_URL is on a different origin\n // from what our page is served on. This might happen if a CDN is used to\n // serve assets; see https://github.com/facebook/create-react-app/issues/2374\n return;\n }\n\n window.addEventListener('load', () => {\n const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;\n\n if (isLocalhost) {\n // This is running on localhost. Let's check if a service worker still exists or not.\n checkValidServiceWorker(swUrl, config);\n\n // Add some additional logging to localhost, pointing developers to the\n // service worker/PWA documentation.\n navigator.serviceWorker.ready.then(() => {\n console.log(\n 'This web app is being served cache-first by a service ' +\n 'worker. To learn more, visit https://bit.ly/CRA-PWA'\n );\n });\n } else {\n // Is not localhost. Just register service worker\n registerValidSW(swUrl, config);\n }\n });\n }\n}\n\nfunction registerValidSW(swUrl, config) {\n navigator.serviceWorker\n .register(swUrl)\n .then(registration => {\n registration.onupdatefound = () => {\n const installingWorker = registration.installing;\n if (installingWorker == null) {\n return;\n }\n installingWorker.onstatechange = () => {\n if (installingWorker.state === 'installed') {\n if (navigator.serviceWorker.controller) {\n // At this point, the updated precached content has been fetched,\n // but the previous service worker will still serve the older\n // content until all client tabs are closed.\n console.log(\n 'New content is available and will be used when all ' +\n 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'\n );\n\n // Execute callback\n if (config && config.onUpdate) {\n config.onUpdate(registration);\n }\n } else {\n // At this point, everything has been precached.\n // It's the perfect time to display a\n // \"Content is cached for offline use.\" message.\n console.log('Content is cached for offline use.');\n\n // Execute callback\n if (config && config.onSuccess) {\n config.onSuccess(registration);\n }\n }\n }\n };\n };\n })\n .catch(error => {\n console.error('Error during service worker registration:', error);\n });\n}\n\nfunction checkValidServiceWorker(swUrl, config) {\n // Check if the service worker can be found. If it can't reload the page.\n fetch(swUrl, {\n headers: { 'Service-Worker': 'script' },\n })\n .then(response => {\n // Ensure service worker exists, and that we really are getting a JS file.\n const contentType = response.headers.get('content-type');\n if (\n response.status === 404 ||\n (contentType != null && contentType.indexOf('javascript') === -1)\n ) {\n // No service worker found. Probably a different app. Reload the page.\n navigator.serviceWorker.ready.then(registration => {\n registration.unregister().then(() => {\n window.location.reload();\n });\n });\n } else {\n // Service worker found. Proceed as normal.\n registerValidSW(swUrl, config);\n }\n })\n .catch(() => {\n console.log(\n 'No internet connection found. App is running in offline mode.'\n );\n });\n}\n\nexport function unregister() {\n if ('serviceWorker' in navigator) {\n navigator.serviceWorker.ready\n .then(registration => {\n registration.unregister();\n })\n .catch(error => {\n console.error(error.message);\n });\n }\n}\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport * as serviceWorker from './serviceWorker';\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want your app to work offline and load faster, you can change\n// unregister() to register() below. Note this comes with some pitfalls.\n// Learn more about service workers: https://bit.ly/CRA-PWA\nserviceWorker.unregister();\n"],"sourceRoot":""}
\ No newline at end of file
diff --git a/front/src/components/devices/Light.js b/front/src/components/devices/Light.js
index 002524cc3..7e6a5c3f8 100644
--- a/front/src/components/devices/Light.js
+++ b/front/src/components/devices/Light.js
@@ -13,7 +13,7 @@ class Light extends React.Component {
}
var color = 'yellow';
- if (this.props.device.traits.includes("action.devices.traits.ColorSetting")){
+ if (this.props.device.traits.includes("action.devices.traits.ColorSetting" && Object.keys(this.props.status).includes("color"))){
if (Object.keys(this.props.status.color).includes("spectrumRgb"))
color = "#" + this.props.status.color.spectrumRgb.toString(16);
else
diff --git a/front/src/components/pages/System.js b/front/src/components/pages/System.js
index f4bf0ec35..a23a39480 100644
--- a/front/src/components/pages/System.js
+++ b/front/src/components/pages/System.js
@@ -130,7 +130,7 @@ class System extends React.Component {
console.error(awa.statusText);
}
}
- }.bind(this)
+ }
awa.open("GET", root + "test/");
awa.setRequestHeader('authorization', 'baerer ' + getCookieValue('token'))
awa.send();
@@ -198,10 +198,6 @@ class System extends React.Component {
textAlign: 'left'
}
- const red_text = {
- color: 'red'
- }
-
const components = this.state.components.map((component) =>
);