diff --git a/.gitignore b/.gitignore index 48ab09a..912659b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ $RECYCLE.BIN/ *.zip *.txt !LICENCE.txt -!histo.txt +!HISTO.txt *.swp include/config.php *_old.php diff --git a/README.md b/README.md index 7719a61..fd54e10 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # phpMyHue -Php web interface to manage Philips Hue lights in a lan. +Php web interface to manage Philips Hue lights in a local network. ## Main Functionnalities * **Full group management** @@ -16,13 +16,14 @@ Php web interface to manage Philips Hue lights in a lan. * Hue effects web service available with 'main.php' ([see wiki](https://github.com/FredBardin/phpMyHue/wiki/Web-services)) * ... -ie: lights screen in english +**Screenshots** +Lights screen in english ![screenshot](screen1_pmh.jpg) -ie: scenes screen in french +Scenes screen in french ![screenshot](screen2_pmh.jpg) -ie: effects screen in english +Effects screen in english ![screenshot](screen3_pmh.gif) ## Installation diff --git a/details.php b/details.php index a2030f0..b3505f3 100644 --- a/details.php +++ b/details.php @@ -12,6 +12,7 @@ include 'include/hueapi.php'; @$rt=$_REQUEST['rt']; +@$nohide=$_REQUEST['nh']; // if set : doesn't hide details tab switch ($rt) { @@ -22,14 +23,17 @@ $HueAPI->loadInfo("lights"); $HueAPI->assignLightsGroup(); case "effects" : + case "rules" : include 'include/'.$rt.'_details.php'; break; - case "adm" : - break; } +if (! isset($nohide)){ ?> + diff --git a/histo.txt b/histo.txt index 90a8236..9e3d7c2 100644 --- a/histo.txt +++ b/histo.txt @@ -6,4 +6,9 @@ v1.2.2 - 16/07/2015 : Update logo in code and screenshots v1.3 - 07/11/2015 : Add Automatic Configuration v1.4 - 13/12/2015 : Add Effects scripts v1.4.1 - 28/12/2015 : Correction to manage white only lights (='dimmable light' type) - +v1.4.2 - 05/05/2016 : add new effect sample +v1.5 - 05/03/2016 : + - Add Sensors Rules management + - Update color conversion with new formulas from meethue + - Now, manage also 'on' status in setcolor/getcolor effect execution (not only color status) + - Update some sample effects with save/restore original status diff --git a/include/about.php b/include/about.php index a8a9f18..20b4ba9 100644 --- a/include/about.php +++ b/include/about.php @@ -9,8 +9,8 @@ -
phpMyHue 1.4.1
F. Bardin 12-2015
+
phpMyHue 1.5
F. Bardin 03-2016
Bridge IP :
Current language : diff --git a/include/effects_details.php b/include/effects_details.php index 3c40b79..4184f81 100644 --- a/include/effects_details.php +++ b/include/effects_details.php @@ -26,13 +26,12 @@ echo "
"; -echo "
"; +echo "
"; ?> \n"; +} // selOperator + +//------------------------------------------------------- +// Function to display the action method selbox +// For reminder : put, post, delete +//------------------------------------------------------- +function selMethod($selmethid,$methval){ + echo "\n"; + + echo "\n"; +} // selMethod + ?> diff --git a/include/huecolor.php b/include/huecolor.php index 84f962c..4270ae6 100644 --- a/include/huecolor.php +++ b/include/huecolor.php @@ -68,9 +68,9 @@ function RGBToXy($RGB){ $b = $b / 255; // Apply gamma correction - $r = ($r > 0.04055 ? pow(($r + 0.055) / 1.055, 2.4) : ($r / 12.92)); - $g = ($g > 0.04055 ? pow(($g + 0.055) / 1.055, 2.4) : ($g / 12.92)); - $b = ($b > 0.04055 ? pow(($b + 0.055) / 1.055, 2.4) : ($b / 12.92)); + $r = ($r > 0.04045 ? pow(($r + 0.055) / 1.055, 2.4) : ($r / 12.92)); + $g = ($g > 0.04045 ? pow(($g + 0.055) / 1.055, 2.4) : ($g / 12.92)); + $b = ($b > 0.04045 ? pow(($b + 0.055) / 1.055, 2.4) : ($b / 12.92)); // Convert to XYZ $X = $r * 0.649926 + $g * 0.103455 + $b * 0.197109; diff --git a/include/hueeffect.php b/include/hueeffect.php index 4337dbf..992c25d 100644 --- a/include/hueeffect.php +++ b/include/hueeffect.php @@ -24,10 +24,11 @@ // or : set light/group id with attributes values // : call a scene by name // : set a timer for n.m second -// : get light id color and save it under a name (in colormode format) -// : put a saved color on a given light (default) or group id (+[transitiontime]) +// : get light id on+color and save it under a name (in colormode format) +// : put a saved on+color on a given light (default) or group id (+[transitiontime]) //---------------------------------------------------- // F. Bardin 14/11/2015 +// 11/07/2015 : add 'on' state to getcolor/setcolor //==================================================== // Anti-hack if (! defined('ANTI_HACK')){exit;} @@ -347,7 +348,7 @@ private function processTimer(){ } // processTimer //------------------------------------------------------------- - // Get color from a light and save it + // Get color and 'on' status from a light and save it // Remark : color is get from colormode value (hs or xy or ct) //------------------------------------------------------------- private function getColor(){ @@ -374,6 +375,8 @@ private function getColor(){ $this->ha->loadInfo("lights"); $lstate = &$this->ha->info['lights'][$id]['state']; + if ($lstate['on'] == ""){$this->color[$name]['on'] = "false";} + else {$this->color[$name]['on'] = "true";} $this->color[$name]['colormode'] = $lstate['colormode']; $this->color[$name]['bri'] = $lstate['bri']; switch ($lstate['colormode']){ @@ -391,7 +394,9 @@ private function getColor(){ } if ($this->debug){ echo str_repeat($this->indent,$this->nodelvl); - echo $this->indent."colormode="; + echo $this->indent."on="; + echo $this->color[$name]['on']." "; + echo "colormode="; echo $this->color[$name]['colormode']." "; echo "bri="; echo $this->color[$name]['bri']." "; @@ -459,7 +464,7 @@ private function setColor(){ if ($type == "light") {$action = $type."s/$id/state";} else {$action = $type."s/$id/action";} - $json = '{"bri" : '.$this->color[$name]['bri'].','; + $json = '{"on" : '.$this->color[$name]['on'].',"bri" : '.$this->color[$name]['bri'].','; switch ($this->color[$name]['colormode']){ case "hs" : $json .= '"hue" : '.$this->color[$name]['hue'].','; diff --git a/include/rules.php b/include/rules.php new file mode 100644 index 0000000..87fdab9 --- /dev/null +++ b/include/rules.php @@ -0,0 +1,41 @@ +loadInfo("sensors"); + +?> + +name array +$a_sname=""; +foreach ($HueAPI->info['sensors'] as $sensorid => $sval){ + $a_sname[$sensorid] = $sval['name']; +} +asort($a_sname); + +// Display sensors +echo ""; +echo ""; + echo "
".$trs["Sensor"]."".$trs["Type"]; +$oldname = ""; +foreach ($a_sname as $sensorid => $sname){ + echo "\n
"; + echo ""; + echo ""; +} +echo "
"; +?> + + + diff --git a/include/rules_details.php b/include/rules_details.php new file mode 100644 index 0000000..8c41769 --- /dev/null +++ b/include/rules_details.php @@ -0,0 +1,151 @@ +loadInfo("rules"); + +$maxelem = 4; // Max allowed conditions or actions + +// Display selected sensor rules +$rulesnum=0; +$srules = array(); +foreach ($HueAPI->info['rules'] as $ruleid => $rval) +{ + // Look for conditions on selected sensor + if (preg_match("/\/sensors\/$sensorid/",$rval['conditions']['0']['address'])){ + $rulesnum++; + $srules[$ruleid] = $rval; + } +} +// If no rule : auto select CREATE option +if ($rulesnum == 0){$selruleid="0";} + +echo ""; +echo ""; +echo "
".$trs["Rule"]; +echo "\n"; + +//==> Ajouter bouton supprimer si selection d'une regle + +if(! isset($selruleid) or $selruleid == ""){ + echo "
"; +} else { + // Init displayed fields if creation + if ($selruleid == 0){ + $srules[$selruleid]['name'] = ""; + $srules[$selruleid]['status'] = "enabled"; + $srules[$selruleid]['conditions']['0']['address'] = ""; + $srules[$selruleid]['conditions']['0']['operator'] = ""; + $srules[$selruleid]['conditions']['0']['value'] = ""; + $srules[$selruleid]['actions']['0']['address'] = ""; + $srules[$selruleid]['actions']['0']['method'] = "PUT"; + $srules[$selruleid]['actions']['0']['body'] = ""; + } + echo ""; + echo "".$trs['Name']; + echo ""; + + echo " 
"; + echo ""; + echo ""; + echo "
"; // srradio + + // Conditions + echo "\n"; + echo "
".$trs["Conditions"]; + echo " "; + echo ""; + echo ""; + echo ""; + echo ""; + echo "\n"; + echo ""; + echo "
".$trs["Address"]."".$trs["Operator"]."".$trs["Value"]."\n"; + foreach ($srules[$selruleid]['conditions'] as $cond => $cval){getCondRow($sensorid, $cond, $cval);} + echo "
"; + echo "
\n"; + + // Actions + echo "
".$trs["Actions"]; + echo " "; + echo ""; + echo ""; + echo ""; + echo ""; + echo "\n"; + echo ""; + echo "
".$trs["Address"]."".$trs["Method"]."".$trs["Action"]."\n"; + foreach ($srules[$selruleid]['actions'] as $act => $aval){getActRow($act, $aval);} + echo "
"; + echo "".$trs["method_warning"].""; + echo "
\n"; + + // Management buttons (Add/Update+Delete) + echo " "; + echo ""; + + echo " "; + echo ""; + + // Empty div for dialog + echo "
"; +} +?> + diff --git a/include/text_en.json b/include/text_en.json index cb8901d..01b9709 100644 --- a/include/text_en.json +++ b/include/text_en.json @@ -86,5 +86,27 @@ "Execution_trace" : "Execution trace", "Close" : "Close", "Running_please_wait" : "Running, please wait ...", -"Rules" : "Rules" +"Rules" : "Rules", +"Rule" : "Rule", +"Rules_management" : "Rules management by sensor", +"Sensor":"Sensor", +"CREATE_NEW_RULE":"CREATE NEW RULE", +"Status":"Status", +"enabled":"Enabled", +"disabled":"Disabled", +"Conditions":"Condition(s)", +"Address":"Address", +"Operator":"Operator", +"op_dx":"changed", +"Value":"Value", +"Actions":"Action(s)", +"Method":"Method", +"Action":"Action", +"method_warning":"Warning: unless you know what you do, don't play with the 'Method' parameter (default=PUT).", +"Move_up":"Move up", +"Move_down":"Move down", +"Update":"Update", +"Delete":"Delete", +"Add":"Add", +"":"" } diff --git a/include/text_fr.json b/include/text_fr.json index c068260..7d487e0 100644 --- a/include/text_fr.json +++ b/include/text_fr.json @@ -43,7 +43,7 @@ "Select" : "Sélectionner", "or_create" : "ou créer", "Fill_Group" : "Remplir gr", -"Delete_selected_groups" : "Supprimer groupe(s) sélectionne(s)", +"Delete_selected_groups" : "Supprimer groupe(s) sélectionné(s)", "Delete_groups" : "Supprimer groupe(s)", "Informations" : "Informations", "Light_id":"Id lumière", @@ -86,5 +86,27 @@ "Execution_trace" : "Trace d'exécution", "Close" : "Fermer", "Running_please_wait" : "Exécution en cours, attendre svp ...", -"Rules" : "Règles" +"Rules" : "Règles", +"Rule" : "Règle", +"Rules_management" : "Gestion règles par senseur", +"Sensor":"Senseur", +"CREATE_NEW_RULE":"CREER NOUVELLE REGLE", +"Status":"Statut", +"enabled":"Activé", +"disabled":"Désactivé", +"Conditions":"Condition(s)", +"Address":"Adresse", +"Operator":"Operateur", +"op_dx":"changé", +"Value":"Valeur", +"Actions":"Action(s)", +"Method":"Méthode", +"Action":"Action", +"method_warning":"Attention : à moins que vous sachiez ce que vous faites, ne jouez pas avec le paramètre 'Méthode' (défaut=PUT).", +"Move_up":"Monter", +"Move_down":"Descendre", +"Update":"Mettre à jour", +"Delete":"Supprimer", +"Add":"Ajouter", +"":"" } diff --git a/index.php b/index.php index f04779e..d0982a8 100644 --- a/index.php +++ b/index.php @@ -51,6 +51,7 @@
  • ">
  • ">
  • ">
  • +
  • ">
  • ">
  • diff --git a/js/functions.js b/js/functions.js index 951ccc4..e22e64c 100644 --- a/js/functions.js +++ b/js/functions.js @@ -1,9 +1,17 @@ // Javascript Functions for phpMyHue // F. Bardin 2015/02/10 -// ----------------------------------- -/*==================================== - Generic Functions -=====================================*/ +//------------------------------------------------------------------------ +// Functions list : +// isMobile returns true/false if navigator is used from a mobile device +// uniqid generates a pseudo unique id of 13 char (+ prefix if supplied) +// $.scrollbarWidth returns the scroll bar width of the navigator in pixels +// scrollCurrentTab enables vertical scroll of a tab id if needed +// msg displays a normal message or an error then fades it out +// processReturnMsg processes return message send by the bridge and display it with msg() +// getCurrentTabsID returns the current tab id of a given tab object +// lightList manage list list event (for light tab or scene detail tab) +// switchGroup switch on or off a group of lamps +//------------------------------------------------------------------------ //---------------------------------------- // Create fonctions for mobiles detection //---------------------------------------- diff --git a/js/lights.js b/js/lights.js index b4ddcd6..b5473cf 100644 --- a/js/lights.js +++ b/js/lights.js @@ -199,6 +199,7 @@ function loadSelectedLightsDetail(tablights){ //--------------------------------------- // Execute action from lights detail tab +// Parameters : action [,xy color value] //--------------------------------------- function lightsDetailAction(tabaction,xy){ var type = ""; diff --git a/js/rules.js b/js/rules.js new file mode 100644 index 0000000..6a8020a --- /dev/null +++ b/js/rules.js @@ -0,0 +1,447 @@ +/*------------------------- + Functions for rules tab + F. Bardin 05/03/2016 + -------------------------*/ + +//--------------------------------------- +// Globals for rules details tab +//--------------------------------------- +var nbcond, nbact; // number of rows for condition or action +var nextcondid, nextactid; // next id for condition or action +var selcond, selact; // selected row for condition or action +var tabdetail = "#"+getCurrentTabsID("#detail"); +var rowmaxelem = 4; // Max number of elements in a row + +//======================================= +// Function for rules tab +//======================================= +function rulesTab(){ + scrollCurrentTab("#tabs"); + + // Get selector for Div ID of current tab + var tabrules = "#"+getCurrentTabsID("#tabs"); + + // Trigger sensor selection + $("#tabs td span.ui-icon input").click(function(){ + $(this).change(); + }); + // Select sensor rules when a new selection occurs + $("#tabs input[type=radio][name=seradio]").change(function(){ + $("#tabs span.ui-icon-arrow-1-e").each(function(){ + $(this).removeClass("ui-icon-arrow-1-e"); + $(this).addClass("ui-icon-radio-off"); + $(this).parent("td").parent("tr").removeClass("ui-state-focus"); + }); + var cbspan = $(this).parent("span"); + cbspan.parent("td").parent("tr").addClass("ui-state-focus"); + cbspan.removeClass("ui-icon-radio-off"); + cbspan.addClass("ui-icon-arrow-1-e"); + // Load detail tab with sensor rules + var sensorid = $(this).attr("id"); + $(tabdetail).load("details.php?rt=rules&sensor="+sensorid, function(){ + $("#detail").show("slide"); + scrollCurrentTab("#detail"); + }); + }); +} // rulesTab + +//======================================= +// Functions for rules details tab +//======================================= +//--------------------------------------- +// Trigger row selection +// Select a row for conditions or actions acts as a radio button +// Row selection impacts button enable/disable +//--------------------------------------- +function catchRowSelection(objectid){ + $(objectid).change(function() { + var id=$(this).attr("id"); + var selClass=$(this).attr("class"); + var pref=selClass.substr(0,1); // get 'c' or 'a' + var buttonList="#"+pref+"del"; + if (! $("#"+id).parent("span").hasClass("cbchecked")){ // if not checked, remove existing checked + $(tabdetail+" tbody span.cbchecked input."+selClass).prop("checked",false); + $(tabdetail+" tbody span.cbchecked input."+selClass).parent("span").removeClass("cbchecked"); + // The current row is checked --> Enable buttons + $(buttonList).button("option", "disabled", false); + + // Stored clicked row and disable up/down button if needed + var selrow = $(this).parent("span").parent("td").parent("tr").index(); + var tableid; + if (pref == "c"){ + selcond = selrow; + tableid = "condtable"; + } else { + selact = selrow; + tableid = "acttable"; + } + updateUpDownState(tableid); + + } else { // The current row is unchecked --> disable buttons + buttonList="#"+pref+"mvup, #"+pref+"mvdn, "+buttonList; + $(buttonList).button("option", "disabled", true); + if (pref == "c"){selcond = "";} + else {selact = "";} + } + $("#"+id).parent("span").toggleClass("cbchecked"); + }); +} // catchRowSelection + +//--------------------------------------- +// Trigger operator change +//--------------------------------------- +function catchSelopeChange(objectid){ + $(objectid).on("selectmenuchange", function (event,val) { + var condnum = $(this).attr("id").substr(7); // id = "sbcond_"+cond + var valope = $(this).val(); + var valid = "cval"+condnum; + if (valope == "dx"){$("#"+valid).hide();} + else {$("#"+valid).show();} + }); +} // catchSelopeChange + +//-------------------------------------------------- +// Set the state (enable/disable) of the tables buttons +// These buttons are : up, down, delete, add +//-------------------------------------------------- +function setButtonsState(){ + // Table conditions buttons + if (nbcond == 1){ + $(tabdetail+" tbody input.csel").hide(0); + $("#cmvup, #cmvdn, #cdel").button("option", "disabled", true); + } else { + $(tabdetail+" tbody input.csel").filter(":first").show(0); + } + if (nbcond == rowmaxelem) {$("#cadd").button("option", "disabled", true);} + else {$("#cadd").button("option", "disabled", false);} + + // Table actions buttons + if (nbact == 1){ + $(tabdetail+" tbody input.asel").hide(0); + $("#amvup, #amvdn, #adel").button("option", "disabled", true); + } else { + $(tabdetail+" tbody input.asel").filter(":first").show(0); + } + if (nbact == rowmaxelem){$("#aadd").button("option", "disabled", true);} + else {$("#aadd").button("option", "disabled", false);} +} // setButtonsState + +//---------------------------------------------------------- +// Update up and down button depending on the selected row +// parameter : tableid = id of table buttons +//---------------------------------------------------------- +function updateUpDownState(tableid){ + var selrow, nbrow, pref; + // Init values + if (tableid == "condtable"){ + selrow = selcond; + nbrow = nbcond; + pref = "c"; + } else { + selrow = selact; + nbrow = nbact; + pref = "a"; + } + if (selrow == 1){ // if 1st row : disable up button + $("#"+pref+"mvup").button("option","disabled", true); + if (nbrow > 1){ + $("#"+pref+"mvdn").button("option","disabled", false); + } + } else { + $("#"+pref+"mvup").button("option","disabled", false); + if (selrow == nbrow){ // if last row : disable down button + $("#"+pref+"mvdn").button("option","disabled", true); + } else { + $("#"+pref+"mvdn").button("option","disabled", false); + } + } +} // updateUpDownState + +//--------------------------------------- +// Initialize the rows count with displayed rule +//--------------------------------------- +function InitRowsCount(){ + nbcond = $(tabdetail+" tbody input.csel").length; + nbact = $(tabdetail+" tbody input.asel").length; + nextcondid = nbcond; + nextactid = nbact; + setButtonsState(); +} // InitRowsCount + +//--------------------------------------- +// Function for 'sensor' rules detail tab +//--------------------------------------- +function sensorRulesDetail(){ + InitRowsCount(); + + // Trigger rule display on selection + $("#srsel").on("selectmenuchange", function (event,val) { + var sensorid = $("#sensorid").val(); + var ruleid = $(this).val(); + $(tabdetail).load("details.php?rt=rules&nh=&sensor="+sensorid+"&rule="+ruleid, function(){ + scrollCurrentTab("#detail"); + }); + // re-Initialize rows counters and buttons + InitRowsCount(); + }); + + // Trigger row selection and operator change + $(tabdetail+" tbody input.csel,"+tabdetail+" tbody input.asel").each(function(){ + catchRowSelection(this); + }); + $(tabdetail+" .selope").each(function(){ + catchSelopeChange(this); + }); + + // Manage buttons trigger for tables + $("#cmvup").click(function(){mvUpSelectedDetail("condtable");}); + $("#cmvdn").click(function(){mvDownSelectedDetail("condtable");}); + $("#cdel").click(function(){delSelectedDetail("condtable");}); + $("#cadd").click(function(){addCond();}); + $("#amvup").click(function(){mvUpSelectedDetail("acttable");}); + $("#amvdn").click(function(){mvDownSelectedDetail("acttable");}); + $("#adel").click(function(){delSelectedDetail("acttable");}); + $("#aadd").click(function(){addAct();}); + + // Manage update of rule + $("#rupd").click(function(){updateRule();}); + $("#rdel").click(function(){deleteRule();}); +} // sensorRulesDetail + +//----------------------------------------------------- +// Move up a table row +// parameter : +// - tableid = id the table where the row is to move up +//----------------------------------------------------- +function mvUpSelectedDetail(tableid){ + var rowcontent = $("#"+tableid+" tbody span.cbchecked").parent("TD").parent("TR").detach(); + var rowindex; + if (tableid == "condtable") { + rowindex = selcond - 1; + selcond--; + } else { + rowindex = selact - 1; + selact--; + } + $("#"+tableid+" tr").eq(rowindex).before(rowcontent); + updateUpDownState(tableid); +} // mvUpSelectedDetail + +//----------------------------------------------------- +// Move down a table row +// parameter : +// - tableid = id the table where the row is to move down +//----------------------------------------------------- +function mvDownSelectedDetail(tableid){ + var rowcontent = $("#"+tableid+" tbody span.cbchecked").parent("TD").parent("TR").detach(); + var rowindex; + if (tableid == "condtable") { + rowindex = selcond; + selcond++; + } else { + rowindex = selact; + selact++; + } + $("#"+tableid+" tr").eq(rowindex).after(rowcontent); + updateUpDownState(tableid); +} // mvDownSelectedDetail + +//----------------------------------------------------- +// Delete selected row +// parameters : +// - tableid = id the table where the row is to delete +//----------------------------------------------------- +function delSelectedDetail(tableid){ + $("#"+tableid+" tbody span.cbchecked").parent("TD").parent("TR").each(function(){ + $(this).remove(); + var pref; + if (tableid == "condtable"){ + nbcond--; + pref = "c"; + } else { + nbact--; + pref = "a"; + } + // Row deleted = no selection --> disable buttions + var buttonList="#"+pref+"mvup, #"+pref+"mvdn, #"+pref+"del"; + $(buttonList).button("option", "disabled", true); + setButtonsState(); + }); +} // delSelectedDetail + +//----------------------------------------------------- +// Add new condition row +//----------------------------------------------------- +function addCond(){ + var sensorid = $("#sensorid").val(); + $("#condtable").append(""); + $("#condtable tr:last").load('main.php?rt=addcond&sensorid='+sensorid+'&cond='+nextcondid, function(){ + $("#condcb_"+nextcondid).each(function(){catchRowSelection(this);}); + $("#sbcond_"+nextcondid).each(function(){catchSelopeChange(this);}); + nbcond++; + nextcondid++; + setButtonsState(); + }); +} // addCond + +//----------------------------------------------------- +// Add new action row +//----------------------------------------------------- +function addAct(){ + $("#acttable").append(''); + $("#acttable tr:last").load('main.php?rt=addact&act='+nextactid, function(){ + $("#actcb_"+nextactid).each(function(){catchRowSelection(this);}); + nbact++; + nextactid++; + setButtonsState(); + }); +} // addAct + +//----------------------------------------------------- +// Update rule with current display +//----------------------------------------------------- +function updateRule(){ + // Get values + var sensorid = $("#sensorid").val(); + var ruleid = $("#srsel").val(); + var rule_name = $("#rulename").val(); + var rule_status = $("#srradio [name=srradio]:checked").val(); + + // Get conditions + var tdnum; + var cond,address,operator,value; + cond = ""; + $("#condtable tr").each(function(){ + address = ""; + tdnum = 0; + $(this).find("td").each(function(){ + tdnum++; + switch(tdnum){ + case 1 : // Check box = ignored + break; + case 2 : // Sensor address + address = $(this).find("input").val(); + break; + case 3 : // Operator + operator = $(this).find("select").val(); + break; + case 4 : // Value + value = $(this).find("input").val(); + break; + } + }); + if (address != "" && operator != ""){ + if (cond != ""){cond += ",";} + cond += '{"address":"/sensors/'+sensorid+'/'+address+'","operator":"'+operator+'"'; + if (operator != "dx"){ + cond += ',"value":"'+value+'"'; + } + cond += '}'; + } + }); + + // Get actions + var act,method,body; + act = ""; + $("#acttable tr").each(function(){ + address = ""; + tdnum = 0; + $(this).find("td").each(function(){ + tdnum++; + switch(tdnum){ + case 1 : // Check box = ignored + break; + case 2 : // Action address + address = $(this).find("input").val(); + break; + case 3 : // Method + method = $(this).find("select").val(); + break; + case 4 : // Json body send as action + body = $(this).find("input").val(); + break; + } + }); + if (address != "" && method != ""){ + if (act != ""){act += ",";} + act += '{"address":"'+address+'","method":"'+method+'"'; + act += ',"body":{'+body+'}'; + act += '}'; + } + }); + + // Create json string only if condition and action exist + if (cond != "" && act != ""){ + var cmdjs = "&cmdjs={"; + cmdjs += '"name":"'+rule_name+'","status":"'+rule_status+'",'; + cmdjs += '"conditions":['+cond+'],'; + cmdjs += '"actions":['+act+']'; + cmdjs += "}"; + + // Send request + var action = "rules"; + var method = "&method="; // Create by default + if (ruleid == "0"){ // Create + method += "POST"; + } else { // Update + action += "/"+ruleid; + method += "PUT"; + } + + $.getJSON('hueapi_cmd.php?action='+action+cmdjs+method, (function(jsmsg){ + if (processReturnMsg(jsmsg)){ + var successMsg; + if (ruleid == "0"){ + ruleid = jsmsg[0].success.id; + successMsg = trs.Created; + } else { + successMsg = trs.Updated; + } + msg(trs.Rule+' '+ruleid+' "'+rule_name+'" '+successMsg); + + // re-display tab + $(tabdetail).load("details.php?rt=rules&nh=&sensor="+sensorid+"&rule="+ruleid, function(){ + scrollCurrentTab("#detail"); + }); + // re-Initialize rows counters and buttons + InitRowsCount(); + } + })); + } +} // updateRule + +//----------------------------------------------------- +// Update rule with current display +//----------------------------------------------------- +function deleteRule(){ + var ruleid = $("#srsel").val(); + var action = "rules/"+ruleid; + var method = "&method=DELETE"; + + // Confirmation required before delete + // TODO add text localisation in dialog + $("#deldialog").dialog({ + title : "Delete selected rule", + resizable: false, + modal: true, + buttons: { + "Delete": function() { + $.getJSON('hueapi_cmd.php?action='+action+method, (function(jsmsg){ + if (processReturnMsg(jsmsg,trs.Rule+' '+trs.Deleted)){ + var sensorid = $("#sensorid").val(); + $(tabdetail).load("details.php?rt=rules&nh=&sensor="+sensorid, function(){ + scrollCurrentTab("#detail"); + }); + } + })); + $(this).dialog("close"); + }, + Cancel: function() { + $(this).dialog("close"); + } + } + }); + + +} // deleteRule + diff --git a/main.php b/main.php index e88512b..66a4d66 100644 --- a/main.php +++ b/main.php @@ -27,6 +27,9 @@ case "effects" : include 'include/effects.php'; break; + case "rules" : + include 'include/rules.php'; + break; case "about" : include 'include/about.php'; break; @@ -64,5 +67,16 @@ $rgb = $_REQUEST['rgb']; echo RGBToXy($rgb); break; + case "addcond" : // add a condition row + include 'include/functions.php'; + $sensorid = $_REQUEST['sensorid']; + $cond = $_REQUEST['cond']; + getCondRow($sensorid, $cond, array(), true); + break; + case "addact" : // add an action row + include 'include/functions.php'; + $act = $_REQUEST['act']; + getActRow($act, array(), true); + break; } ?> diff --git a/themes/style.css b/themes/style.css index 46d4947..d592909 100644 --- a/themes/style.css +++ b/themes/style.css @@ -265,6 +265,10 @@ HIL002 : 2 lamps (2 bottom) #tsradio { float: left; } +.aligntxt { + position: relative; + bottom: .8em; +} @-moz-document url-prefix() { #creategrp { @@ -276,6 +280,11 @@ HIL002 : 2 lamps (2 bottom) top: .15em; } } +#srradio { + float: left; + position: relative; + top: -.1em; +} #grpassign { float: right; }