Commit 3236b18f authored by nextime's avatar nextime

Clima thermostats interface is now complete and fully working

parent bf28fdba
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -68,6 +68,10 @@ ...@@ -68,6 +68,10 @@
} }
*/ */
function jQueryEscapesel(expression) {
return expression.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~]/g, '\\$&');
}
(function () { (function () {
var previousScroll = 0; var previousScroll = 0;
......
...@@ -39,6 +39,7 @@ js/starthammer.js ...@@ -39,6 +39,7 @@ js/starthammer.js
../../resources/js/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js ../../resources/js/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js
../../resources/js/raphael.min.js ../../resources/js/raphael.min.js
../../resources/js/justgage.js ../../resources/js/justgage.js
../../resources/js/json2.js
../../resources/js/ResizeSensor.js ../../resources/js/ResizeSensor.js
../../resources/css-element-queries/src/ElementQueries.js ../../resources/css-element-queries/src/ElementQueries.js
js/fastclick.js js/fastclick.js
......
...@@ -66,7 +66,7 @@ if($panel && is_array($panel)) { ...@@ -66,7 +66,7 @@ if($panel && is_array($panel)) {
<div class="notifylist"> <div class="notifylist">
<div class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>" data-snap-ignore="true"> <div class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>" data-snap-ignore="true">
<? foreach($climastatuses as $cs) { ?> <? foreach($climastatuses as $cs) { ?>
<button type="button" style="width:100%;margin-top:5px;" <button type="button" style="width:100%;margin-top:5px;<?if($climastatus==$cs['clima_status'])echo'display:none';?>"
data-domotika-statusselect="<?=$cs['clima_status']?>" data-domotika-statusselect="<?=$cs['clima_status']?>"
data-domotika-type="statusselect" data-domotika-type="statusselect"
data-domotika-panel="thermo-statuschooselist-<?=$button['id']."-".$panel['id']?>" data-domotika-panel="thermo-statuschooselist-<?=$button['id']."-".$panel['id']?>"
...@@ -110,14 +110,16 @@ if($panel && is_array($panel)) { ...@@ -110,14 +110,16 @@ if($panel && is_array($panel)) {
</div> </div>
</div> </div>
<div style="margin-top:45px;"> <div style="margin-top:45px;">
<button type="button" class="btn btn-gray " <button type="button" class="btn btn-<?if($thermo['function']=='manual'){echo 'primary';}else{echo 'gray';}?>"
id="thermo-btnmanual-<?=$button['id']."-".$panel['id']?>" id="thermo-btnmanual-<?=$button['id']."-".$panel['id']?>"
data-domotika-thermostat="<?=$panel['panel_content']?>"
data-dmcolor-on="btn-primary" data-dmcolor-on="btn-primary"
data-dmcolor-off="btn-gray" data-dmcolor-off="btn-gray"
data-domotika-type="btnmanual" data-domotika-type="btnmanual"
style="width:150px;height:40px;"><b>Manual</b></button> style="width:150px;height:40px;"><b>Manual</b></button>
<button type="button" class="btn btn-primary " <button type="button" class="btn btn-<?if($thermo['function']=='program'){echo 'primary';}else{echo 'gray';}?>"
id="thermo-btnprogram-<?=$button['id']."-".$panel['id']?>" id="thermo-btnprogram-<?=$button['id']."-".$panel['id']?>"
data-domotika-thermostat="<?=$panel['panel_content']?>"
data-dmcolor-on="btn-primary" data-dmcolor-on="btn-primary"
data-dmcolor-off="btn-gray" data-dmcolor-off="btn-gray"
data-domotika-type="btnprogram" data-domotika-type="btnprogram"
......
...@@ -68,6 +68,8 @@ if($panel && is_array($panel)) { ...@@ -68,6 +68,8 @@ if($panel && is_array($panel)) {
<div style="width:100%;margin:0 auto;text-align:center;margin-bottom:10px;"> <div style="width:100%;margin:0 auto;text-align:center;margin-bottom:10px;">
<button type="button" data-domotika-type="btn-statuses" <button type="button" data-domotika-type="btn-statuses"
id="thermo-btnstatus-<?=$button['id']."-".$panel['id']?>" id="thermo-btnstatus-<?=$button['id']."-".$panel['id']?>"
data-domotika-actualstatus="<?=$climastatus?>"
data-domotika-btnthermoname="<?=$button['name']?>"
class="btn btn-primary" style="width:150px;height:40px;"><b><?=$climastatus?></b> class="btn btn-primary" style="width:150px;height:40px;"><b><?=$climastatus?></b>
<i class="glyphicon glyphicon-chevron-down"></i> <i class="glyphicon glyphicon-chevron-down"></i>
</button> </button>
...@@ -76,13 +78,13 @@ if($panel && is_array($panel)) { ...@@ -76,13 +78,13 @@ if($panel && is_array($panel)) {
class="panel panel-theme-<?=$_DOMOTIKA['gui_theme']?> thermo-statuspanel text-on-white-theme-<?=$_DOMOTIKA['gui_theme']?>"> class="panel panel-theme-<?=$_DOMOTIKA['gui_theme']?> thermo-statuspanel text-on-white-theme-<?=$_DOMOTIKA['gui_theme']?>">
<div class="notifylist"> <div class="notifylist">
<div class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>" data-snap-ignore="true"> <div class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>" data-snap-ignore="true">
<? foreach($climastatuses as $cs) { if($cs['clima_status']!=$climastatus) { ?> <? foreach($climastatuses as $cs) {?>
<button type="button" style="width:100%;margin-top:5px;" <button type="button" style="width:100%;margin-top:5px;<?if($cs['clima_status']==$climastatus)echo'display:none';?>"
data-domotika-statuschoose="<?=$cs['clima_status']?>" data-domotika-statuschoose="<?=$cs['clima_status']?>"
data-domotika-type="statuschoose" data-domotika-type="statuschoose"
data-domotika-panel="thermo-statuslist-<?=$button['id']."-".$panel['id']?>" data-domotika-panel="thermo-statuslist-<?=$button['id']."-".$panel['id']?>"
class="btn btn-success"><?=$cs['clima_status']?></button> class="btn btn-success"><?=$cs['clima_status']?></button>
<? }} ?> <? }?>
</div> </div>
</div> </div>
</div> </div>
...@@ -118,6 +120,10 @@ if($panel && is_array($panel)) { ...@@ -118,6 +120,10 @@ if($panel && is_array($panel)) {
<div class="noUI-thermo-program" data-domotika-thermo-startvalue="<?=$the['h'.zfill($i,2)]?>" <div class="noUI-thermo-program" data-domotika-thermo-startvalue="<?=$the['h'.zfill($i,2)]?>"
data-domotika-thermo-minslide="<?=$button['minslide']?>" data-domotika-thermo-minslide="<?=$button['minslide']?>"
data-domotika-thermo-maxslide="<?=$button['maxslide']?>" data-domotika-thermo-maxslide="<?=$button['maxslide']?>"
data-domotika-level-thermoname="<?=$button['name']?>"
data-domotika-level-statusname="<?=$climastatus?>"
data-domotika-level-day="<?=$d?>"
data-domotika-level-hour="<?='h'.zfill($i,2)?>"
id="thermo-levels-<?=$button['id']."-".$panel['id']."-".$d."-".$i?>" data-domotika-type="thermoprogram"> id="thermo-levels-<?=$button['id']."-".$panel['id']."-".$d."-".$i?>" data-domotika-type="thermoprogram">
</div> </div>
<button type="button" <button type="button"
...@@ -145,6 +151,10 @@ if($panel && is_array($panel)) { ...@@ -145,6 +151,10 @@ if($panel && is_array($panel)) {
<div class="noUI-thermo-program" data-domotika-thermo-startvalue="<?=$the['h'.zfill($i,2)]?>" <div class="noUI-thermo-program" data-domotika-thermo-startvalue="<?=$the['h'.zfill($i,2)]?>"
data-domotika-thermo-minslide="<?=$button['minslide']?>" data-domotika-thermo-minslide="<?=$button['minslide']?>"
data-domotika-thermo-maxslide="<?=$button['maxslide']?>" data-domotika-thermo-maxslide="<?=$button['maxslide']?>"
data-domotika-level-thermoname="<?=$button['name']?>"
data-domotika-level-statusname="<?=$climastatus?>"
data-domotika-level-day="<?=$d?>"
data-domotika-level-hour="<?='h'.zfill($i,2)?>"
id="thermo-levels-<?=$button['id']."-".$panel['id']."-".$d."-".$i?>" data-domotika-type="thermoprogram"> id="thermo-levels-<?=$button['id']."-".$panel['id']."-".$d."-".$i?>" data-domotika-type="thermoprogram">
</div> </div>
<button type="button" <button type="button"
...@@ -165,9 +175,11 @@ if($panel && is_array($panel)) { ...@@ -165,9 +175,11 @@ if($panel && is_array($panel)) {
<div style="width:100%;margin:0 auto;text-align:center;"> <div style="width:100%;margin:0 auto;text-align:center;">
<button type="button" id=thermo-reset-<?=$button['id']."-".$panel['id']?> <button type="button" id=thermo-reset-<?=$button['id']."-".$panel['id']?>
data-domotika-type=thermo-reset data-domotika-type=thermo-reset
data-domotika-thermostat="<?=$button['name']?>"
class="btn btn-success" disabled style="width:150px;height:40px;"><b>RESET CHANGES</b></button> class="btn btn-success" disabled style="width:150px;height:40px;"><b>RESET CHANGES</b></button>
<button type="button" id=thermo-save-<?=$button['id']."-".$panel['id']?> <button type="button" id=thermo-save-<?=$button['id']."-".$panel['id']?>
data-domotika-type=thermo-save data-domotika-type=thermo-save
data-domotika-thermostat="<?=$button['name']?>"
class="btn btn-danger" disabled style="width:150px;height:40px;"><b>SAVE & APPLY</b></button> class="btn btn-danger" disabled style="width:150px;height:40px;"><b>SAVE & APPLY</b></button>
</div> </div>
......
...@@ -34,16 +34,23 @@ function changeClimaStatus(newstatus, request){ ...@@ -34,16 +34,23 @@ function changeClimaStatus(newstatus, request){
} }
} }
function changeThermostatStatus(newstatus, parts2, parts3) function changeThermostatStatus(newstatus, parts2, parts3, nopost)
{ {
var program=$("#thermo-btnprogram-"+parts2+'-'+parts3); var program=$("#thermo-btnprogram-"+parts2+'-'+parts3);
var manual=$("#thermo-btnmanual-"+parts2+'-'+parts3); var manual=$("#thermo-btnmanual-"+parts2+'-'+parts3);
var slide=$("#thermo-level-"+parts2+'-'+parts3);
if(typeof(nopost)=='undefined')
nopost=false;
if(newstatus=='manual'){ if(newstatus=='manual'){
program.alterClass(program.attr('data-dmcolor-on'), program.attr('data-dmcolor-off')); program.alterClass(program.attr('data-dmcolor-on'), program.attr('data-dmcolor-off'));
manual.alterClass(manual.attr('data-dmcolor-off'), manual.attr('data-dmcolor-on')); manual.alterClass(manual.attr('data-dmcolor-off'), manual.attr('data-dmcolor-on'));
if(!nopost)
$.post("/rest/v1.2/clima/thermostat/"+manual.attr('data-domotika-thermostat')+"/json", 'function=manual&set='+slide.val().toString());
} else { } else {
program.alterClass(program.attr('data-dmcolor-off'), program.attr('data-dmcolor-on')); program.alterClass(program.attr('data-dmcolor-off'), program.attr('data-dmcolor-on'));
manual.alterClass(manual.attr('data-dmcolor-on'), manual.attr('data-dmcolor-off')); manual.alterClass(manual.attr('data-dmcolor-on'), manual.attr('data-dmcolor-off'));
if(!nopost)
$.post("/rest/v1.2/clima/thermostat/"+manual.attr('data-domotika-thermostat')+"/json", 'function=program');
} }
} }
...@@ -52,10 +59,10 @@ function checkSliderSet(slider){ ...@@ -52,10 +59,10 @@ function checkSliderSet(slider){
{ {
if(Date.now()-slider.data('lastchanged')>1000) if(Date.now()-slider.data('lastchanged')>1000)
{ {
console.debug(slider.data('lastchanged'));
console.debug(Date.now());
console.debug('------------------------');
slider.data('lastchanged', false); slider.data('lastchanged', false);
var parts=slider.attr('id').split('-');
changeThermostatStatus('manual', parts[2], parts[3]);
} }
} }
if(slider.val()!=slider.data('oldval')) if(slider.val()!=slider.data('oldval'))
...@@ -80,8 +87,7 @@ $("[data-domotika-type=thermo-level]").each( ...@@ -80,8 +87,7 @@ $("[data-domotika-type=thermo-level]").each(
var parts=$(this).attr('id').split("-"); var parts=$(this).attr('id').split("-");
$("#thermo-showset-"+parts[2]+'-'+parts[3]).text(parseFloat($(this).val()).toFixed(1)); $("#thermo-showset-"+parts[2]+'-'+parts[3]).text(parseFloat($(this).val()).toFixed(1));
thermoResetGaugeLevel('gauge-'+parts[2]+'-'+parts[3], parseFloat($(this).val())); thermoResetGaugeLevel('gauge-'+parts[2]+'-'+parts[3], parseFloat($(this).val()));
changeThermostatStatus('manual', parts[2], parts[3]); }
},
}); });
$(this).data('oldval', $(this).val()); $(this).data('oldval', $(this).val());
$(this).data('lastchanged', false); $(this).data('lastchanged', false);
...@@ -101,7 +107,6 @@ $("[data-domotika-type=thermo-level]").each( ...@@ -101,7 +107,6 @@ $("[data-domotika-type=thermo-level]").each(
{ {
$('#'+$(this).attr('id').replace('thermo-level-','thermo-showset-')).text(parseFloat($(this).val()).toFixed(1)); $('#'+$(this).attr('id').replace('thermo-level-','thermo-showset-')).text(parseFloat($(this).val()).toFixed(1));
thermoResetGaugeLevel('gauge-'+parts[2]+'-'+parts[3], parseFloat($(this).val())); thermoResetGaugeLevel('gauge-'+parts[2]+'-'+parts[3], parseFloat($(this).val()));
changeThermostatStatus('manual', parts[2], parts[3]);
} }
}); });
...@@ -112,16 +117,12 @@ $("[data-domotika-type=thermo-level]").each( ...@@ -112,16 +117,12 @@ $("[data-domotika-type=thermo-level]").each(
var slide=$('#'+$(this).attr('id').replace('thermo-minus-','thermo-level-')); var slide=$('#'+$(this).attr('id').replace('thermo-minus-','thermo-level-'));
slide.val(parseFloat(slide.val())-0.5); slide.val(parseFloat(slide.val())-0.5);
$('#'+$(this).attr('id').replace('thermo-minus-','thermo-showset-')).text(parseFloat(slide.val()).toFixed(1)); $('#'+$(this).attr('id').replace('thermo-minus-','thermo-showset-')).text(parseFloat(slide.val()).toFixed(1));
var parts=$(this).attr('id').split("-");
changeThermostatStatus('manual', parts[2], parts[3]);
}, 200, 700, true); }, 200, 700, true);
plus.continouoshold(function(){ plus.continouoshold(function(){
var slide=$('#'+$(this).attr('id').replace('thermo-plus-','thermo-level-')); var slide=$('#'+$(this).attr('id').replace('thermo-plus-','thermo-level-'));
slide.val(parseFloat(slide.val())+0.5); slide.val(parseFloat(slide.val())+0.5);
$('#'+$(this).attr('id').replace('thermo-plus-','thermo-showset-')).text(parseFloat(slide.val()).toFixed(1)); $('#'+$(this).attr('id').replace('thermo-plus-','thermo-showset-')).text(parseFloat(slide.val()).toFixed(1));
var parts=$(this).attr('id').split("-");
changeThermostatStatus('manual', parts[2], parts[3]);
}, 200, 700, true); }, 200, 700, true);
} }
...@@ -172,5 +173,34 @@ $("[data-domotika-type=btnmanual]").each( ...@@ -172,5 +173,34 @@ $("[data-domotika-type=btnmanual]").each(
} }
); );
var thermostatEvent = function(event) {
var data=$.parseJSON(event.data);
console.debug(data);
if(typeof(data.data.action) != 'undefined'){
var action=data.data.action;
if(action=='climastatus'){
changeClimaStatus(data.data.status);
}else if(action=='function'){
$("[data-domotika-thermostat="+jQueryEscapesel(data.data.thermostat)+"][data-domotika-type=btnprogram]").each(
function(){
var parts=$(this).attr('id').split("-");
changeThermostatStatus(data.data.func, parts[2], parts[3], true);
}
);
}else if(action=='setval'){
$("[data-domotika-thermostat="+jQueryEscapesel(data.data.thermostat)+"][data-domotika-type=btnprogram]").each(
function(){
var parts=$(this).attr('id').split("-");
var slide=$("#thermo-level-"+parts[2]+'-'+parts[3]);
slide.val(parseFloat(data.data.val));
$('#thermo-showset-'+parts[2]+'-'+parts[3]).text(parseFloat(data.data.val).toFixed(1));
}
);
}
}
}
es.addEventListener("thermostat", thermostatEvent);
</script> </script>
<? @include_once("../../includes/common.php"); ?> <? @include_once("../../includes/common.php"); ?>
<script> <script>
function loadThermoProgs(parts2, parts3){
$('#thermo-reset-'+parts2+'-'+parts3).prop('disabled', true);
$('#thermo-save-'+parts2+'-'+parts3).prop('disabled', true);
var climastatus=$("#thermo-btnstatus-"+parts2+'-'+parts3).attr("data-domotika-actualstatus");
var thermoname=$('#thermo-reset-'+parts2+'-'+parts3).attr('data-domotika-thermostat');
console.debug('loadThermoProgs '+thermoname+' '+climastatus);
$.get("/rest/v1.2/clima/program/"+thermoname+"/"+climastatus+"/json", function(r){
for(i=0;i<r.data.length;i++){
d=r.data[i];
var slidesel="[data-domotika-level-statusname="+jQueryEscapesel(climastatus)+"]";
slidesel+="[data-domotika-level-thermoname="+jQueryEscapesel(thermoname)+"]";
slidesel+="[data-domotika-level-day="+d.day+"]";
$(slidesel).each(
function(){
$(this).val(d[$(this).attr('data-domotika-level-hour')]);
}
);
}
}
);
}
function changeProgClimaStatus(newstatus, parts2, parts3){
$("#thermo-btnstatus-"+parts2+"-"+parts3).each(
function(){
$(this).html("<b>"+newstatus+'<b> <i class="glyphicon glyphicon-chevron-down"></i>')
$(this).attr("data-domotika-actualstatus", newstatus);
}
);
var thermoname=$("#thermo-btnstatus-"+parts2+"-"+parts3).attr('data-domotika-btnthermoname');
$("[data-domotika-level-thermoname="+jQueryEscapesel(thermoname)+"]").each(
function(){
$(this).attr('data-domotika-level-statusname', newstatus);
}
);
$("[data-domotika-type=statuschoose]").each(
function(){
if($(this).attr('data-domotika-statuschoose')==newstatus)
$(this).hide();
else
$(this).show();
}
);
loadThermoProgs(parts2, parts3);
}
$("[data-domotika-type=thermoprogram]").each( $("[data-domotika-type=thermoprogram]").each(
function(){ function(){
$(this).noUiSlider({ $(this).noUiSlider({
...@@ -74,6 +122,9 @@ $("[data-domotika-type=statuschoose]").each( ...@@ -74,6 +122,9 @@ $("[data-domotika-type=statuschoose]").each(
$(this).fastClick(function(){ $(this).fastClick(function(){
var panel="#"+$(this).attr('data-domotika-panel'); var panel="#"+$(this).attr('data-domotika-panel');
$(panel).hide(150); $(panel).hide(150);
var newstatus=$(this).attr('data-domotika-statuschoose');
var parts=$(this).attr('data-domotika-panel').split("-");
changeProgClimaStatus(newstatus, parts[2], parts[3]);
}); });
} }
); );
...@@ -84,6 +135,30 @@ $("[data-domotika-type=thermo-save]").each( ...@@ -84,6 +135,30 @@ $("[data-domotika-type=thermo-save]").each(
var parts=$(this).attr('id').split("-"); var parts=$(this).attr('id').split("-");
$(this).prop('disabled', true); $(this).prop('disabled', true);
$('#thermo-reset-'+parts[2]+'-'+parts[3]).prop('disabled', true); $('#thermo-reset-'+parts[2]+'-'+parts[3]).prop('disabled', true);
var climastatus=$("#thermo-btnstatus-"+parts[2]+'-'+parts[3]).attr("data-domotika-actualstatus");
var thermoname=$('#thermo-reset-'+parts[2]+'-'+parts[3]).attr('data-domotika-thermostat');
var slidesel="[data-domotika-level-statusname="+jQueryEscapesel(climastatus)+"]";
slidesel+="[data-domotika-level-thermoname="+jQueryEscapesel(thermoname)+"]";
var postdata={'thermoname': thermoname, 'climastatus': climastatus,
'mon':{},'tue':{},'wed':{},'thu':{},'fri':{},'sat':{},'sun':{}
};
$(slidesel).each(
function(){
var day=$(this).attr('data-domotika-level-day');
var hour=$(this).attr('data-domotika-level-hour');
postdata[day][hour]=parseFloat($(this).val());
}
);
$.ajax({
type:'POST',
url:"/rest/v1.2/clima/program/"+thermoname+"/"+climastatus+"/json",
contentType:"application/json; charset=utf-8",
data: JSON.stringify(postdata),
dataType:"json",
success: function(r){
console.debug('thermostat program saved');
}
});
}); });
} }
); );
...@@ -92,8 +167,7 @@ $("[data-domotika-type=thermo-reset]").each( ...@@ -92,8 +167,7 @@ $("[data-domotika-type=thermo-reset]").each(
function(){ function(){
$(this).on('click', function(){ $(this).on('click', function(){
var parts=$(this).attr('id').split("-"); var parts=$(this).attr('id').split("-");
$(this).prop('disabled', true); loadThermoProgs(parts[2], parts[3]);
$('#thermo-save-'+parts[2]+'-'+parts[3]).prop('disabled', true);
}); });
} }
); );
...@@ -107,4 +181,26 @@ $(function () { ...@@ -107,4 +181,26 @@ $(function () {
$('.thermotab a:first').tab('show'); $('.thermotab a:first').tab('show');
}); });
var thermoProgramEvent = function(event) {
var data=$.parseJSON(event.data);
console.debug(data);
if(typeof(data.data.action) != 'undefined'){
var action=data.data.action;
if(action=='updated'){
var thermostat=data.data.thermostat;
var climastatus=data.data.climastatus;
jsel="[data-domotika-actualstatus="+jQueryEscapesel(climastatus)+"]";
jsel+="[data-domotika-btnthermoname="+jQueryEscapesel(thermostat)+"]";
$(jsel).each(
function(){
var parts=$(this).attr('id').split('-')
loadThermoProgs(parts[2], parts[3]);
}
);
}
}
}
es.addEventListener("thermoprogram", thermoProgramEvent);
</script> </script>
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
<script type="text/javascript" src="/resources/css-element-queries/src/ElementQueries.js"></script> <script type="text/javascript" src="/resources/css-element-queries/src/ElementQueries.js"></script>
<script type="text/javascript" src="/resources/js/raphael.min.js"></script> <script type="text/javascript" src="/resources/js/raphael.min.js"></script>
<script type="text/javascript" src="/resources/js/justgage.js"></script> <script type="text/javascript" src="/resources/js/justgage.js"></script>
<script type="text/javascript" src="/resources/js/json2.js"></script>
<script type="text/javascript" src="/resources/noUiSlider/jquery.nouislider.js"></script> <script type="text/javascript" src="/resources/noUiSlider/jquery.nouislider.js"></script>
<script src="<?=$BASEGUIPATH;?>/js/fastclick.js"></script> <script src="<?=$BASEGUIPATH;?>/js/fastclick.js"></script>
<script src="<?=$BASEGUIPATH;?>/js/speech.js"></script> <script src="<?=$BASEGUIPATH;?>/js/speech.js"></script>
......
This diff is collapsed.
...@@ -243,51 +243,6 @@ class ThermostatsProgs(DBObject): ...@@ -243,51 +243,6 @@ class ThermostatsProgs(DBObject):
TABLENAME="thermostats_progs" TABLENAME="thermostats_progs"
def cleanFlags():
Registry.getConfig().delete("flags", where=["expire<="+str(time.time())])
def insertFlag(name, expire=None):
if expire:
expire="'"+str(expire)+"'"
else:
expire="NULL"
qstr="INSERT INTO flags (name,expire) VALUES ('"+name+"',"+expire
qstr+=") ON DUPLICATE KEY UPDATE expire="+expire
return Registry.DBPOOL.runOperation(qstr)
def setUnique(name, value):
t=time.time()
querystr="""INSERT INTO uniques (name,value,lastupdate) VALUES ('%s', '%s', '%s')
ON DUPLICATE KEY UPDATE value='%s',lastupdate='%s' """ % (str(name), str(value),str(t), str(value),str(t))
return Registry.DBPOOL.runOperation(querystr)
def updateNetStatus(nst):
return setUnique('netstatus',nst)
def _retValueQuery(res, defval='DEFAULT'):
if res:
return res.value
else:
return defval
def getNetStatus():
return Uniques.find(where=["name='netstatus'"],limit=1).addCallback(_retValueQuery, 'DEFAULT')
def getClimaStatus():
return Uniques.find(where=["name='climastatus'"],limit=1).addCallback(_retValueQuery, 'OFF')
def getStatusRealtime(stname):
return StatusRealtime.find(where=["status_name=?", stname],limit=1).addCallback(_retValueQuery, False)
def _getStatusAction(res):
if res:
return res
return []
def getStatusAction(stname):
return StatusActions.find(where=["status_name=? AND active=1", stname]).addCallback(_getStatusAction)
def updateStatusRealtime(stname, status, changed=False): def updateStatusRealtime(stname, status, changed=False):
querystr="INSERT INTO statusrealtime (status_name,value,lastupdate" querystr="INSERT INTO statusrealtime (status_name,value,lastupdate"
if changed: if changed:
...@@ -654,6 +609,96 @@ def getLongestUpdatedBoard(num=1): ...@@ -654,6 +609,96 @@ def getLongestUpdatedBoard(num=1):
def getBoardById(bid=0): def getBoardById(bid=0):
return DMBoards.find(where=["id=?", bid], limit=1) return DMBoards.find(where=["id=?", bid], limit=1)
def cleanFlags():
Registry.getConfig().delete("flags", where=["expire<="+str(time.time())])
def insertFlag(name, expire=None):
if expire:
expire="'"+str(expire)+"'"
else:
expire="NULL"
qstr="INSERT INTO flags (name,expire) VALUES ('"+name+"',"+expire
qstr+=") ON DUPLICATE KEY UPDATE expire="+expire
return Registry.DBPOOL.runOperation(qstr)
def setUnique(name, value):
t=time.time()
querystr="""INSERT INTO uniques (name,value,lastupdate) VALUES ('%s', '%s', '%s')
ON DUPLICATE KEY UPDATE value='%s',lastupdate='%s' """ % (str(name), str(value),str(t), str(value),str(t))
return Registry.DBPOOL.runOperation(querystr)
def updateNetStatus(nst):
return setUnique('netstatus',nst)
def _retValueQuery(res, defval='DEFAULT'):
if res:
return res.value
else:
return defval
def getNetStatus():
return Uniques.find(where=["name='netstatus'"],limit=1).addCallback(_retValueQuery, 'DEFAULT')
def getClimaStatus():
return Uniques.find(where=["name='climastatus'"],limit=1).addCallback(_retValueQuery, 'OFF')
def getStatusRealtime(stname):
return StatusRealtime.find(where=["status_name=?", stname],limit=1).addCallback(_retValueQuery, False)
def _getStatusAction(res):
if res:
return res
return []
def getStatusAction(stname):
return StatusActions.find(where=["status_name=? AND active=1", stname]).addCallback(_getStatusAction)
def _setThermostat(res, thermostat, func, setval):
if res:
if func and func in ['manual','program']:
res.function=func
if setval:
res.setval=float(setval)
res.save()
return res
return False
def setThermostat(thermostat, func=False, setval=False):
return Thermostats.find(where=['name=?', thermostat],limit=1).addCallback(_setThermostat, thermostat, func, setval)
def _setThermostatProgsDict(res, thermostat, climastatus, r):
ret=False
if res:
for d in ['mon','tue','wed','thu','fri','sat','sun']:
if d in r.keys() and type(r[d]).__name__=='dict':
sql="UPDATE thermostats_progs SET "
doit=False
for h in range(1, 25):
hour='h'+str(h).zfill(2)
if hour in r[d].keys() and genutils.is_number(r[d][hour]):
if float(r[d][hour]) >= float(res.minslide) and float(r[d][hour]) <= float(res.maxslide):
ret=True
if doit:
sql+=","
sql+=hour+"="+str(r[d][hour])
doit=True
if doit:
where=" WHERE thermostat_name='%s' AND clima_status='%s' AND day='%s'" %(str(thermostat),str(climastatus),str(d))
runQuery(sql+where)
ret=True
if ret:
return defer.succeed(True)
else:
return defer.fail(False)
def setThermostatProgsDict(thermostat, climastatus, r):
return Thermostats.find(where=['name=?', thermostat], limit=1).addCallback(
_setThermostatProgsDict, thermostat, climastatus, r)
def checkMotionDetectionEvent(camera, zone, estatus, etype): def checkMotionDetectionEvent(camera, zone, estatus, etype):
qstr="""active>0 AND (event_status=%d OR event_status=255) qstr="""active>0 AND (event_status=%d OR event_status=255)
...@@ -849,3 +894,5 @@ def getChartData(chartname): ...@@ -849,3 +894,5 @@ def getChartData(chartname):
def getChartSeries(chartname): def getChartSeries(chartname):
log.debug("SELECT * FROM stats_charts_series WHERE active=1 AND name='%s'" % str(chartname)) log.debug("SELECT * FROM stats_charts_series WHERE active=1 AND name='%s'" % str(chartname))
return StatsChartsSeries.find(where=["name='%s'" % str(chartname)]) return StatsChartsSeries.find(where=["name='%s'" % str(chartname)])
...@@ -2326,10 +2326,29 @@ class domotikaService(service.Service): ...@@ -2326,10 +2326,29 @@ class domotikaService(service.Service):
return dmdb.getClimaStatus() return dmdb.getClimaStatus()
def web_on_setClimaStatus(self, newstatus): def web_on_setClimaStatus(self, newstatus):
self.clientSend('thermostat', {'action':'climastatus', 'status':newstatus})
return dmdb.setUnique('climastatus', newstatus); return dmdb.setUnique('climastatus', newstatus);
def web_on_getThermostat(self, thermostat): def web_on_getThermostat(self, thermostat):
return dmdb.Thermostats.find(where=["name='%s'" % thermostat],limit=1) return dmdb.Thermostats.find(where=["name=?",thermostat],limit=1)
def web_on_setThermostat(self, thermostat, func=False, setval=False):
if setval!=False and genutils.is_number(setval):
self.clientSend('thermostat', {'action':'setval', 'val': setval, 'thermostat': thermostat})
if func and func in ['manual','program']:
self.clientSend('thermostat', {'action':'function', 'func':func, 'thermostat': thermostat})
return dmdb.setThermostat(thermostat, func, setval)
def web_on_getThermostatProgram(self, thermostat, climastatus):
return dmdb.ThermostatsProgs.find(where=["thermostat_name=? and clima_status=?",thermostat, climastatus])
def web_on_setThermostatProgram(self, thermostat, climastatus, r):
def broad(res):
data={'thermostat': thermostat, 'climastatus': climastatus, 'action':'updated'}
self.clientSend('thermoprogram', data)
return res
return dmdb.setThermostatProgsDict(thermostat,climastatus,r).addCallback(broad)
def web_on_voiceReceived(self, txt, confidence=0.0, lang="it"): def web_on_voiceReceived(self, txt, confidence=0.0, lang="it"):
return self.voiceRecognized(txt, confidence, lang, voicesrc='RestAPI') return self.voiceRecognized(txt, confidence, lang, voicesrc='RestAPI')
...@@ -2505,3 +2524,4 @@ class domotikaService(service.Service): ...@@ -2505,3 +2524,4 @@ class domotikaService(service.Service):
def board_on_boardOK(self, bid): def board_on_boardOK(self, bid):
self.clientSend('boardOK', bid) self.clientSend('boardOK', bid)
...@@ -251,21 +251,36 @@ class RestCore(object): ...@@ -251,21 +251,36 @@ class RestCore(object):
pass pass
if request.method in (Http.POST,Http.PUT) and HttpHeader.CONTENT_TYPE in request.received_headers.keys(): if request.method in (Http.POST,Http.PUT) and HttpHeader.CONTENT_TYPE in request.received_headers.keys():
contentType = request.received_headers["content-type"] contentType = request.received_headers["content-type"]
if contentType == MediaType.APPLICATION_JSON: if contentType.split(";")[0] == MediaType.APPLICATION_JSON:
try:
request.json = json.loads(request.data) if request.data else {}
try: try:
r = dict(rargs.items() + request.json.items()) r = dict(rargs.items() + request.json.items())
except: except:
r = request.json r = request.json
elif contentType in (MediaType.APPLICATION_XML,MediaType.TEXT_XML): except Exception as ex:
raise TypeError("Unable to parse JSON body: %s" % ex)
elif contentType.split(";")[0] in (MediaType.APPLICATION_XML,MediaType.TEXT_XML):
try:
request.xml = ElementTree.XML(request.data)
try: try:
r = dict(rargs.items() + request.xml.items()) r = dict(rargs.items() + request.xml.items())
except: except:
r = request.xml r = request.xml
elif contentType == MediaType.TEXT_YAML: except Exception as ex:
raise TypeError("Unable to parse XML body: %s" % ex)
elif contentType.split(";")[0] == MediaType.TEXT_YAML:
try:
request.yaml = yaml.safe_load(request.data)
try: try:
r = dict(rargs.items() + request.xml.yaml()) r = dict(rargs.items() + request.xml.yaml())
except: except:
r = request.xml.yaml r = request.xml.yaml
except Exception as ex:
raise TypeError("Unable to parse YAML body: %s" % ex)
else: else:
r = rargs r = rargs
else: else:
...@@ -273,8 +288,6 @@ class RestCore(object): ...@@ -273,8 +288,6 @@ class RestCore(object):
return r return r
class BaseRest(RestCore): class BaseRest(RestCore):
@route("/") @route("/")
...@@ -548,6 +561,28 @@ class ClimaRest(RestCore): ...@@ -548,6 +561,28 @@ class ClimaRest(RestCore):
return self.callbackResponse(self.core.getThermostat(thermostat), request) return self.callbackResponse(self.core.getThermostat(thermostat), request)
@route("/thermostat/<thermostat>",(Http.PUT,Http.POST))
@wrapResponse
def setThermostat(self, request, thermostat, *a, **kw):
r = self._getRequestArgs(request)
func=False
if 'function' in r.keys() and r['function'] in ['manual','program']:
func=r['function']
setval=False
if 'set' in r.keys() and genutils.is_number(r['set']):
setval=r['set']
return self.callbackResponse(self.core.setThermostat(thermostat, func, setval), request)
@route("/program/<thermostat>/<climastatus>",(Http.GET))
@wrapResponse
def getProgram(self, request, thermostat, climastatus, *a, **kw):
return self.callbackResponse(self.core.getThermostatProgram(thermostat, climastatus), request)
@route("/program/<thermostat>/<climastatus>",(Http.PUT,Http.POST))
@wrapResponse
def setProgram(self, request, thermostat, climastatus, *a, **kw):
r = self._getRequestArgs(request)
return self.callbackResponse(self.core.setThermostatProgram(thermostat, climastatus, r), request)
RESTv12LIST=( RESTv12LIST=(
......
...@@ -199,7 +199,7 @@ class RootPage(rend.Page): ...@@ -199,7 +199,7 @@ class RootPage(rend.Page):
if dbres and len(dbres)>0: if dbres and len(dbres)>0:
session.dmpermissions[request.path]=dbres[0][0] session.dmpermissions[request.path]=dbres[0][0]
if neededPermission(request.method) in session.dmpermissions[request.path]: if neededPermission(request.method) in session.dmpermissions[request.path]:
log.info("PERMISSION DB OK, USER: "+session.mind.perms.username+" SESSION: "+str(session.uid)+" ARGS: "+str(request.args)+" REQ "+str(request)) log.info("PERMISSION DB OK, USER: "+session.mind.perms.username+" SESSION: "+str(session.uid)) #+" ARGS: "+str(request.args)+" REQ "+str(request))
self.core.updateSession(session.uid, session, self) self.core.updateSession(session.uid, session, self)
return rend.Page.locateChild(self, ctx, name) return rend.Page.locateChild(self, ctx, name)
except: except:
...@@ -228,11 +228,11 @@ class RootPage(rend.Page): ...@@ -228,11 +228,11 @@ class RootPage(rend.Page):
if not 'dmpermissions' in dir(session): if not 'dmpermissions' in dir(session):
session.dmpermissions={} session.dmpermissions={}
if request.path in WEB_SYSTEM_PATHS: if request.path in WEB_SYSTEM_PATHS:
log.info("WEB_SYSTEM_PATH: USER: "+uname+" SESSION: "+str(session.uid)+" ARGS: "+str(request.args)+" REQ "+str(request)) log.info("WEB_SYSTEM_PATH: USER: "+uname+" SESSION: "+str(session.uid)) #+" ARGS: "+str(request.args)+" REQ "+str(request))
return rend.Page.locateChild(self, ctx, name) return rend.Page.locateChild(self, ctx, name)
if request.path in session.dmpermissions.keys(): if request.path in session.dmpermissions.keys():
if neededPermission(request.method) in session.dmpermissions[request.path]: if neededPermission(request.method) in session.dmpermissions[request.path]:
log.debug("PERMISSION OK, SESSION: "+str(session.uid)+" ARGS: "+str(request.args)+" REQ "+str(request)) log.debug("PERMISSION OK, SESSION: "+str(session.uid)) #+" ARGS: "+str(request.args)+" REQ "+str(request))
self.core.updateSession(session.uid, session, self) self.core.updateSession(session.uid, session, self)
return rend.Page.locateChild(self, ctx, name) return rend.Page.locateChild(self, ctx, name)
else: else:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment