Commit 55779de9 authored by nextime's avatar nextime

* Added graph panel, added rvc_src in actions table

parent 6afbbc87
ALTER TABLE `users` ADD `left_bar` ENUM( 'all', 'none', 'visible-sm', 'visible-md', 'visible-lg', 'hidden-sm', 'hidden-md', 'hidden-lg' ) NOT NULL DEFAULT 'hidden-sm',
ADD `right_bar` ENUM( 'all', 'none', 'visible-sm', 'visible-md', 'visible-lg', 'hidden-sm', 'hidden-md', 'hidden-lg' ) NOT NULL DEFAULT 'hidden-sm';
ALTER TABLE `actions` ADD `rcv_src` VARCHAR( 32 ) NOT NULL DEFAULT '*' AFTER `rcv_dst` ,
ADD INDEX ( `rcv_src` ) ;
ALTER TABLE `stats_charts_series` CHANGE `selector_type` `selector_type` ENUM( 'SQL', 'daily_sum', 'hourly_sum' ) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 'SQL';
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -163,17 +163,31 @@ ...@@ -163,17 +163,31 @@
/*bottom: 50px;*/ /*bottom: 50px;*/
padding-top: 50px; padding-top: 50px;
padding-bottom: 55px; padding-bottom: 55px;
padding-left: 20px;
padding-right: 20px;
} }
.theme-dmblack { .theme-dmblack {
background-color: #000; background-color: #000;
} }
.text-on-white-theme-dmblack {
color: #000;
}
.container { .container {
/*padding-top: 100px;*/ /*padding-top: 100px;*/
height:100%; height:100%;
padding-bottom: 20px; /* was 45 */ padding-bottom: 20px; /* was 45 */
} }
.leftbar_enabled {
padding-left: 100px;
}
.rightbar_enabled {
padding-right: 100px;
}
.insider { .insider {
/*margin-top: 20px; /*margin-top: 20px;
margin-bottom: 40px;*/ margin-bottom: 40px;*/
...@@ -533,6 +547,17 @@ body.theme-dmblack { ...@@ -533,6 +547,17 @@ body.theme-dmblack {
.panel-media-low { .panel-media-low {
height: auto !important; height: auto !important;
} }
.leftbar_enabled {
padding-left: 50px;
}
.rightbar_enabled {
padding-right: 50px;
}
.container {
padding-left: 2px;
padding-right: 2px;
}
} }
...@@ -542,13 +567,36 @@ body.theme-dmblack { ...@@ -542,13 +567,36 @@ body.theme-dmblack {
left: 88px; left: 88px;
right: auto; right: auto;
} }
.leftbar_enabled {
padding-left: 50px;
}
.rightbar_enabled {
padding-right: 50px;
}
.primarycontainer {
padding-left: 2px;
padding-right: 2px;
}
} }
@media (max-width: 992px) { @media (max-width: 992px) {
.panel-media-low { .panel-media-low {
height: auto !important; height: auto !important;
} }
.primarycontainer {
padding-left: 2px;
padding-right: 2px;
}
.leftbar_enabled {
padding-left: 50px;
}
.rightbar_enabled {
padding-right: 50px;
}
} }
@media (min-width: 1400px) { @media (min-width: 1400px) {
...@@ -556,6 +604,13 @@ body.theme-dmblack { ...@@ -556,6 +604,13 @@ body.theme-dmblack {
max-width: 1370px; max-width: 1370px;
} }
} }
.leftbar_enabled {
padding-left: 50px;
}
.rightbar_enabled {
padding-right: 50px;
}
@media (min-width: 1600px) { @media (min-width: 1600px) {
.container { .container {
......
...@@ -13,6 +13,8 @@ var updateUser = function(r) { ...@@ -13,6 +13,8 @@ var updateUser = function(r) {
$("#webspeech").val(r.data.webspeech); $("#webspeech").val(r.data.webspeech);
$("#speechlang").val(r.data.speechlang); $("#speechlang").val(r.data.speechlang);
$("#gui_theme").val(r.data.gui_theme); $("#gui_theme").val(r.data.gui_theme);
$("#leftb").val(r.data.left_bar);
$("#rightb").val(r.data.right_bar);
if(r.data.tts==1) if(r.data.tts==1)
$('#tts-switch').bootstrapSwitch('setState', true); //$("#tts").attr('checked', true); $('#tts-switch').bootstrapSwitch('setState', true); //$("#tts").attr('checked', true);
else else
...@@ -34,6 +36,7 @@ $("#userform").on("submit", function(event) { ...@@ -34,6 +36,7 @@ $("#userform").on("submit", function(event) {
popupFader('danger', 'ERROR:','Le password inserite non coincidono'); popupFader('danger', 'ERROR:','Le password inserite non coincidono');
playTTS('Errore, Le password inserite non coincidono'); playTTS('Errore, Le password inserite non coincidono');
} else { } else {
alert($(this).serialize());
$.ajax({url: "/rest/v1.2/users/me/json", type:"PUT", data: $(this).serialize(), $.ajax({url: "/rest/v1.2/users/me/json", type:"PUT", data: $(this).serialize(),
success: function(res) { success: function(res) {
popupFader('success', 'SUCCESS:','Utente aggiornato correttamente...'); popupFader('success', 'SUCCESS:','Utente aggiornato correttamente...');
......
...@@ -39,6 +39,32 @@ include_once("translations.php"); ...@@ -39,6 +39,32 @@ include_once("translations.php");
//print_r($_DOMOTIKA); //print_r($_DOMOTIKA);
switch($_DOMOTIKA['left_bar'])
{
case 'all': $LBAR=array('small','medium','big'); break;
case 'visible-sm': $LBAR=array('small'); break;
case 'visible-md': $LBAR=array('medium'); break;
case 'visible-lg': $LBAR=array('big'); break;
case 'hidden-sm': $LBAR=array('medium','big'); break;
case 'hidden-md': $LBAR=array('small','big'); break;
case 'hidden-lg': $LBAR=array('small','medium'); break;
case 'none': $LBAR=array(); break;
default: $LBAR=array('medium','big');
}
switch($_DOMOTIKA['right_bar'])
{
case 'all': $RBAR=array('small','medium','big'); break;
case 'visible-sm': $RBAR=array('small'); break;
case 'visible-md': $RBAR=array('medium'); break;
case 'visible-lg': $RBAR=array('big'); break;
case 'hidden-sm': $RBAR=array('medium','big'); break;
case 'hidden-md': $RBAR=array('small','big'); break;
case 'hidden-lg': $RBAR=array('small','medium'); break;
case 'none': $RBAR=array(); break;
default: $RBAR=array('medium','big');
}
$lang=$_DOMOTIKA['language']; $lang=$_DOMOTIKA['language'];
$tr = new Translations($lang); $tr = new Translations($lang);
......
...@@ -119,51 +119,52 @@ window.matchMedia=window.matchMedia||function(a){"use strict";var c,d=a.document ...@@ -119,51 +119,52 @@ window.matchMedia=window.matchMedia||function(a){"use strict";var c,d=a.document
} }
*/ */
if(mobile)
{
if(window.navigator.userAgent.match(/firefox/i) && window.navigator.userAgent.match(/mobile/i))
{
var installbutton = $("#installbutton"); if(window.navigator.userAgent.match(/firefox/i) && window.navigator.userAgent.match(/mobile/i))
var port=""; {
if(document.location.port)
var port=":"+document.location.port; var installbutton = $("#installbutton");
<? var port="";
$manif=str_replace("/js/domotika.js","",$BASEGUIPATH); if(document.location.port)
$manif=str_replace("/js/combined.min.js", "", $manif); var port=":"+document.location.port;
?> <?
var manifest_url = document.location.protocol+"//"+document.location.host+port+"<?=$manif?>/manifest.webapp"; $manif=str_replace("/js/domotika.js","",$BASEGUIPATH);
$manif=str_replace("/js/combined.min.js", "", $manif);
?>
var manifest_url = document.location.protocol+"//"+document.location.host+port+"<?=$manif?>/manifest.webapp";
function installFFApp(ev) { function installFFApp(ev) {
ev.preventDefault(); ev.preventDefault();
var myapp = navigator.mozApps.install(manifest_url); var myapp = navigator.mozApps.install(manifest_url);
myapp.onsuccess = function(data) { myapp.onsuccess = function(data) {
$("#install_ff").hide() $("#install_ff").hide()
console.log(this); console.log(this);
popupFader('success', 'SUCCESS:','Web app installata correttamente'); popupFader('success', 'SUCCESS:','Web app installata correttamente');
var a = playTTS('Web app installata correttamente'); var a = playTTS('Web app installata correttamente');
};
myapp.onerror = function() {
console.log('Install failed, error: ' + this.error.name);
popupFader('danger', 'ERROR:', 'App not installed: '+this.error.name);
playTTS('Errore, applicazione non installata');
};
}; };
myapp.onerror = function() {
console.log('Install failed, error: ' + this.error.name);
popupFader('danger', 'ERROR:', 'App not installed: '+this.error.name);
playTTS('Errore, applicazione non installata');
};
};
var installCheck = navigator.mozApps.checkInstalled(manifest_url); var installCheck = navigator.mozApps.checkInstalled(manifest_url);
installCheck.onsuccess = function() { installCheck.onsuccess = function() {
if(installCheck.result) { if(installCheck.result) {
$("#install_ff").hide(); $("#install_ff").hide();
} else { } else {
$("#install_ff").show(); $("#install_ff").show();
installbutton.on('click', installFFApp); installbutton.on('click', installFFApp);
};
}; };
} };
}
if(mobile)
{
if(jQuery.isFunction(window.screen.lockOrientation)) if(jQuery.isFunction(window.screen.lockOrientation))
window.screen.lockOrientation('portrait'); window.screen.lockOrientation('portrait');
else if(jQuery.isFunction(window.screen.mozLockOrientation)) else if(jQuery.isFunction(window.screen.mozLockOrientation))
......
...@@ -34,51 +34,52 @@ ...@@ -34,51 +34,52 @@
} }
*/ */
if(mobile)
{
if(window.navigator.userAgent.match(/firefox/i) && window.navigator.userAgent.match(/mobile/i))
{
var installbutton = $("#installbutton"); if(window.navigator.userAgent.match(/firefox/i) && window.navigator.userAgent.match(/mobile/i))
var port=""; {
if(document.location.port)
var port=":"+document.location.port; var installbutton = $("#installbutton");
<? var port="";
$manif=str_replace("/js/domotika.js","",$BASEGUIPATH); if(document.location.port)
$manif=str_replace("/js/combined.min.js", "", $manif); var port=":"+document.location.port;
?> <?
var manifest_url = document.location.protocol+"//"+document.location.host+port+"<?=$manif?>/manifest.webapp"; $manif=str_replace("/js/domotika.js","",$BASEGUIPATH);
$manif=str_replace("/js/combined.min.js", "", $manif);
?>
var manifest_url = document.location.protocol+"//"+document.location.host+port+"<?=$manif?>/manifest.webapp";
function installFFApp(ev) { function installFFApp(ev) {
ev.preventDefault(); ev.preventDefault();
var myapp = navigator.mozApps.install(manifest_url); var myapp = navigator.mozApps.install(manifest_url);
myapp.onsuccess = function(data) { myapp.onsuccess = function(data) {
$("#install_ff").hide() $("#install_ff").hide()
console.log(this); console.log(this);
popupFader('success', 'SUCCESS:','Web app installata correttamente'); popupFader('success', 'SUCCESS:','Web app installata correttamente');
var a = playTTS('Web app installata correttamente'); var a = playTTS('Web app installata correttamente');
};
myapp.onerror = function() {
console.log('Install failed, error: ' + this.error.name);
popupFader('danger', 'ERROR:', 'App not installed: '+this.error.name);
playTTS('Errore, applicazione non installata');
};
}; };
myapp.onerror = function() {
console.log('Install failed, error: ' + this.error.name);
popupFader('danger', 'ERROR:', 'App not installed: '+this.error.name);
playTTS('Errore, applicazione non installata');
};
};
var installCheck = navigator.mozApps.checkInstalled(manifest_url); var installCheck = navigator.mozApps.checkInstalled(manifest_url);
installCheck.onsuccess = function() { installCheck.onsuccess = function() {
if(installCheck.result) { if(installCheck.result) {
$("#install_ff").hide(); $("#install_ff").hide();
} else { } else {
$("#install_ff").show(); $("#install_ff").show();
installbutton.on('click', installFFApp); installbutton.on('click', installFFApp);
};
}; };
} };
}
if(mobile)
{
if(jQuery.isFunction(window.screen.lockOrientation)) if(jQuery.isFunction(window.screen.lockOrientation))
window.screen.lockOrientation('portrait'); window.screen.lockOrientation('portrait');
else if(jQuery.isFunction(window.screen.mozLockOrientation)) else if(jQuery.isFunction(window.screen.mozLockOrientation))
......
...@@ -100,6 +100,37 @@ ...@@ -100,6 +100,37 @@
</select> </select>
</div> </div>
</div> </div>
<div class="form-group">
<label for="leftb" class="col-lg-2 control-label">Left bar visibility:</label>
<div class="col-lg-3">
<select name="leftb" id="leftb" class="form-control">
<option value="all">All sizes</option>
<option value="none">No</option>
<option value="visible-sm">Small only</option>
<option value="visible-md">Medium only</option>
<option value="visible-lg">Big only</option>
<option value="hidden-sm">All but small</option>
<option value="hidden-md">All but medium</option>
<option value="hidden-lg">All but big</option>
</select>
</div>
</div>
<div class="form-group">
<label for="rightb" class="col-lg-2 control-label">Left bar visibility:</label>
<div class="col-lg-3">
<select name="rightb" id="rightb" class="form-control">
<option value="all">All sizes</option>
<option value="none">No</option>
<option value="visible-sm">Small only</option>
<option value="visible-md">Medium only</option>
<option value="visible-lg">Big only</option>
<option value="hidden-sm">All but small</option>
<option value="hidden-md">All but medium</option>
<option value="hidden-lg">All but big</option>
</select>
</div>
</div>
<div class="form-group"> <div class="form-group">
<label for="mobilehome" class="col-lg-2 control-label"></label> <label for="mobilehome" class="col-lg-2 control-label"></label>
<div class="col-lg-3"> <div class="col-lg-3">
......
...@@ -35,8 +35,8 @@ if($panel && is_array($panel)) { ...@@ -35,8 +35,8 @@ if($panel && is_array($panel)) {
} }
?> ?>
<div class="domotika-panel <?=$dmfull;?>" <?=$dmheight;?>> <div class="domotika-panel <?=$dmfull;?>" <?=$dmheight;?>>
<div class="home-panel" <?=$dmheight;?>> <div class="home-panel chartpanel" <?=$dmheight;?> >
<div class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>"> <div class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>" >
<? <?
foreach($charts as $chart) { foreach($charts as $chart) {
//print_r($chart); //print_r($chart);
......
<? @include_once("../../includes/common.php"); ?> <? @include_once("../../includes/common.php"); ?>
<script type="text/javascript">
$(document).ready(function() {
<? <?
$days = getLastNDays(7, 'Y-m-d' ); $days = getLastNDays(7, 'Y-m-d' );
$daysql = getLastNDays(7, 'Y-m-d'); $daysql = getLastNDays(7, 'Y-m-d');
?>
<script type="text/javascript">
var ajaxCharts = [];
<?
foreach($_SESSION[PANELS_CHARTS] as $eid => $chart) foreach($_SESSION[PANELS_CHARTS] as $eid => $chart)
{ {
$chartserie = getChartData($chart['name']); ?>
?> ajaxCharts[ajaxCharts.length] = {
var plot_<?=$chart['name']?>=$.jqplot('<?=$eid?>', [<? settings: {
$maxseriecount=0; eid: "<?=$eid?>",
for($c=0;$c<count($chartserie);$c++) data_url: "/rest/v1.2/charts/chartbyname/<?=$chart['name']?>/json"
{ },
if($maxseriecount<$chartserie[$c]['count'])
$maxseriecount=$chartserie[$c]['count']; plot: function(settings){
echo $chartserie[$c]['data']; t = this;
if($c<count($chartserie)-1) $.extend(t.settings, settings);
echo ","; $.ajax({
} async:false,
?>], { url: t.settings.data_url,
title:'<?=addslashes($chart['title'])?>', dataType: "json",
legend: { success: function(res){
show: <?=$chart['legend_show']?>, res.data.opt.axes.xaxis.renderer=$.jqplot.DateAxisRenderer;
location:'<?=$chart['legend_position']?>', res.data.opt.axes.xaxis.tickRenderer=$.jqplot.CanvasAxisTickRenderer;
renderOptions: { $("#"+t.settings.eid).empty();
placement: "<?=$chart['legend_placement']?>" $.jqplot(t.settings.eid, res.data.data, res.data.opt);
} }
}, });
grid: { }
shadow: <?=$chart['grid_shadow']?>, };
drawBorder: <?=$chart['grid_border']?>,
background: '<?=$chart['grid_background']?>'
},
axes:{
xaxis: {
renderer:$.jqplot.DateAxisRenderer,
tickRenderer:$.jqplot.CanvasAxisTickRenderer,
autoscale:true,
<?if($chart['x_numberTicks']) {
if($maxseriecount<intval($chart['x_numberTicks'])) {?>
numberTicks: <?=$maxseriecount?>,
<? }else{?>
numberTicks: <?=$chart['x_numberTicks']?>,
<? }?>
<?}?>
tickOptions:{
<?if($chart['x_formatString']) {?>
formatString: <?=$chart['x_formatString']?>,
<?}?>
angle:30
}
},
yaxis: {
min:0,
<?if($chart['y_numberTicks']) {?>
numberTicks: <?=$chart['y_numberTicks']?>,
<?}?>
tickOptions:{
<?if($chart['y_formatString']) {?>
formatString: <?=$chart['y_formatString']?>
<?} else {?>
formatString:'%.<?=$chart['y_label_precision']?>f'
<?}?>
}
}
},
highlighter: {
show: true,
sizeAdjust: 7.5
},
cursor: {
show: false
},
series:[
<?
for($c=0;$c<count($chartserie);$c++)
{
$serie=$chartserie[$c]['serie']
?>
{
label: '<?=addslashes($serie['label'])?>',
lineWidth:<?=$serie['line_width']?>,
markerOptions:{
style:'<?=$serie['marker_style']?>',
size: <?=$serie['marker_size']?>,
},
color:'<?=$serie['color']?>',
showMarker: <?=$serie['marker_show']?>,
showLine: true,
fill: <?=$serie['fill']?>,
fillAndStroke: true,
highlighter: {
formatString:'<?=$serie['highlighter_formatString']?>'
}
}<?
if($c<count($chartserie)-1)
echo ",\n";
}
?>
],
seriesDefaults:{
rendererOptions: {
smooth: true,
shadowAlpha: 0.1,
fillToZero: true
}
}
});
<? <?
} }
?> ?>
function chartsPlot()
{
for(i=0;i<ajaxCharts.length;i++)
{
ajaxCharts[i].plot();
}
}
$(document).ready(function(){
chartsPlot();
setInterval(chartsPlot, 10000);
}); });
//$(".chartpanel").scrollLeft(10000);
</script> </script>
...@@ -13,7 +13,7 @@ if($_DOMOTIKA['gui_theme']=='dmblack') ...@@ -13,7 +13,7 @@ if($_DOMOTIKA['gui_theme']=='dmblack')
<a class="navbar-brand" href="http://www.unixmedia.it" target=_blank>Domotika</a> <a class="navbar-brand" href="http://www.unixmedia.it" target=_blank>Domotika</a>
<p class="navbar-text hidden-sm"><a href="http://www.unixmedia.it" class="navbar-link" target=_blank>by Unixmedia</a></p> <p class="navbar-text hidden-sm"><a href="http://www.unixmedia.it" class="navbar-link" target=_blank>by Unixmedia</a></p>
<button id="speechbutton" type="button" class="btn btn-default navbar-btn pull-right speechbutton"></button> <button id="speechbutton" type="button" class="btn btn-default navbar-btn pull-right speechbutton"></button>
<form id="speech" class="navbar-form footbar-form hidden-sm"> <form id="speech" class="navbar-form footbar-form hidden-sm text-on-white-theme-<?=$_DOMOTIKA['gui_theme']?>">
<input type="text" id="speechinp" name="text" value="" class="form-control" <?=$webspeech?> lang="<?=$_DOMOTIKA['speechlang']?>" placeholder="Command"> <input type="text" id="speechinp" name="text" value="" class="form-control" <?=$webspeech?> lang="<?=$_DOMOTIKA['speechlang']?>" placeholder="Command">
</form> </form>
<form id="speechsm" class="navbar-form footbar-form-sm visible-sm"> <form id="speechsm" class="navbar-form footbar-form-sm visible-sm">
...@@ -24,7 +24,7 @@ if($_DOMOTIKA['gui_theme']=='dmblack') ...@@ -24,7 +24,7 @@ if($_DOMOTIKA['gui_theme']=='dmblack')
</button> </button>
<a class="btn btn-default navbar-btn pull-right homebutton" href="<?=$BASEGUIPATH;?>"></a> <a class="btn btn-default navbar-btn pull-right homebutton" href="<?=$BASEGUIPATH;?>"></a>
<div id="notifypanel" class="panel panel-theme-<?=$_DOMOTIKA['gui_theme']?> notifypanel"> <div id="notifypanel" class="panel panel-theme-<?=$_DOMOTIKA['gui_theme']?> notifypanel text-on-white-theme-<?=$_DOMOTIKA['gui_theme']?>">
<div class="panel-heading panel-head-theme-<?=$_DOMOTIKA['gui_theme']?>"><h4>Notifications<i class="glyphicon glyphicon-remove pull-right" id="notify-removeall"></i></h4></div> <div class="panel-heading panel-head-theme-<?=$_DOMOTIKA['gui_theme']?>"><h4>Notifications<i class="glyphicon glyphicon-remove pull-right" id="notify-removeall"></i></h4></div>
<div class="notifylist"> <div class="notifylist">
<div id="notifications" class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>" data-snap-ignore="true"> <div id="notifications" class="list-group theme-<?=$_DOMOTIKA['gui_theme']?>" data-snap-ignore="true">
......
...@@ -115,7 +115,7 @@ function getChartData($chartname) ...@@ -115,7 +115,7 @@ function getChartData($chartname)
$seriesret=array(); $seriesret=array();
$file = @fopen(parseSelectorName($serie['selector_name'], $serie), "r"); $file = @fopen(parseSelectorName($serie['selector_name'], $serie), "r");
while (!feof($file)) while (!feof($file))
{ {
$currentLine = explode(":", fgets($file)); $currentLine = explode(":", fgets($file));
if(count($currentLine)>=2) if(count($currentLine)>=2)
$seriesret[]=array('x' => $currentLine[0], 'y' => $currentLine[1]); $seriesret[]=array('x' => $currentLine[0], 'y' => $currentLine[1]);
......
...@@ -182,15 +182,6 @@ class Users(DBObject): ...@@ -182,15 +182,6 @@ class Users(DBObject):
class UsersGroup(DBObject): class UsersGroup(DBObject):
TABLENAME="users_groups" TABLENAME="users_groups"
class StatsConf(DBObject):
TABLENAME="stats_conf"
class StatsData(DBObject):
TABLENAME="stats_data"
class StatsHistory(DBObject):
TABLENAME="stats_history"
class EmailConf(DBObject): class EmailConf(DBObject):
TABLENAME="email_conf" TABLENAME="email_conf"
...@@ -218,6 +209,20 @@ class Notifications(DBObject): ...@@ -218,6 +209,20 @@ class Notifications(DBObject):
class Flags(DBObject): class Flags(DBObject):
TABLENAME="flags" TABLENAME="flags"
class StatsCharts(DBObject):
TABLENAME="stats_charts"
class StatsChartsSeries(DBObject):
TABLENAME="stats_charts_series"
class StatsConf(DBObject):
TABLENAME="stats_conf"
class StatsData(DBObject):
TABLENAME="stats_data"
class StatsHistory(DBObject):
TABLENAME="stats_history"
def cleanFlags(): def cleanFlags():
Registry.getConfig().delete("flags", where=["expire<="+str(time.time())]) Registry.getConfig().delete("flags", where=["expire<="+str(time.time())])
...@@ -539,9 +544,13 @@ def matchIncomingPacket(dst, src, msgtype, ctx, act, islocal=False): ...@@ -539,9 +544,13 @@ def matchIncomingPacket(dst, src, msgtype, ctx, act, islocal=False):
localonly="" localonly=""
if not islocal: if not islocal:
localonly="AND local_only=0" localonly="AND local_only=0"
log.debug("rcv_ctx=%s AND rcv_act=%s AND rcv_msgtype=%s AND active=1 %s AND ikap_src!=%s AND ((DMDOMAIN(rcv_dst, '%s')=1 AND exact_dst=0) OR (rcv_dst='%s' AND exact_dst > 0))" %(str(ctx), str(act), str(msgtype), str(localonly), str(src), str(dst), str(dst))) sq="rcv_ctx='%s' AND rcv_act='%s' AND rcv_msgtype='%s' AND active=1 " %(str(ctx), str(act), str(msgtype))
return Actions.find( sq+=localonly
where=['rcv_ctx=? AND rcv_act=? AND rcv_msgtype=? AND active=1 '+localonly+' AND ikap_src!=? AND ((DMDOMAIN(rcv_dst, ?)=1 AND exact_dst=0) OR (rcv_dst=? AND exact_dst > 0))', ctx, act, msgtype, src, dst, dst ]) sq+=" AND ikap_src!='%s'" %(str(src))
sq+=" AND ((DMDOMAIN(rcv_dst, '%s')=1 AND exact_dst=0) OR (rcv_dst='%s' AND exact_dst > 0))" %(str(dst), str(dst))
sq+=" AND (DMDOMAIN('%s',rcv_src)=1 OR rcv_src='')""" %(str(src))
log.debug(sq)
return Actions.find(where=[sq])
def getActionLoops(): def getActionLoops():
...@@ -749,7 +758,8 @@ def getUsersInGroup(group, activeonly=True): ...@@ -749,7 +758,8 @@ def getUsersInGroup(group, activeonly=True):
def updateUserData(username, pwd, email, dhome, mhome, tts=False, def updateUserData(username, pwd, email, dhome, mhome, tts=False,
lang="it",slide=False, webspeech='touch', speechlang='it-IT', theme='dmblack'): lang="it",slide=False, webspeech='touch', speechlang='it-IT',
theme='dmblack',leftb='hidden-sm', rightb='hidden-sm'):
def onRes(res): def onRes(res):
if res>0: if res>0:
return defer.succeed(username+" correctly updated") return defer.succeed(username+" correctly updated")
...@@ -771,6 +781,8 @@ def updateUserData(username, pwd, email, dhome, mhome, tts=False, ...@@ -771,6 +781,8 @@ def updateUserData(username, pwd, email, dhome, mhome, tts=False,
qstring+=",webspeech='%s'" % webspeech qstring+=",webspeech='%s'" % webspeech
qstring+=",speechlang='%s'" % speechlang qstring+=",speechlang='%s'" % speechlang
qstring+=",gui_theme='%s'" % str(theme) qstring+=",gui_theme='%s'" % str(theme)
qstring+=",left_bar='%s'" % str(leftb)
qstring+=",right_bar='%s'" % str(rightb)
qstring+=" WHERE username='%s' AND active > 0" %(username) qstring+=" WHERE username='%s' AND active > 0" %(username)
log.debug(qstring) log.debug(qstring)
return runOperation(qstring).addCallback(onRes) return runOperation(qstring).addCallback(onRes)
...@@ -806,3 +818,11 @@ def getPermissionForPath(user, path): ...@@ -806,3 +818,11 @@ def getPermissionForPath(user, path):
) )
) AS U order by length(selection) DESC,level LIMIT 1""" ) AS U order by length(selection) DESC,level LIMIT 1"""
return runQuery(qstring) return runQuery(qstring)
def getChartData(chartname):
return StatsCharts.find(where=["name='%s'" % str(chartname)])
def getChartSeries(chartname):
log.debug("SELECT * FROM stats_charts_series WHERE active=1 AND name='%s'" % str(chartname))
return StatsChartsSeries.find(where=["name='%s'" % str(chartname)])
...@@ -2194,6 +2194,205 @@ class domotikaService(service.Service): ...@@ -2194,6 +2194,205 @@ class domotikaService(service.Service):
return True return True
def parseChartSeries(self, series, chartdata, chartname):
ret=""
def getSelectorSubtype(serie):
if str(serie.selector_subtype)=='back_in_time':
ret=" AND date >= DATE_ADD(NOW(),"
ret+=" INTERVAL -"+str(serie.selector_numopt)+" DAY)"
elif str(serie.selector_subtype)=='limits':
if serie.selector_start:
ret+=" AND date >= '"+str(serie.selector_start)+"'"
if serie.selector_stop:
ret+=" AND date <= '"+str(serie.selector_stop)+"'"
return ret
def parseSelectorName(cmd, serie):
cmd=cmd.replace("#OPTNUM#", str(serie.selector_numopt))
cmd=cmd.replace("#NAME#", str(serie.name))
cmd=cmd.replace("#START#",str(serie.selector_start))
cmd=cmd.replace("#STOP#",str(serie.selector_stop))
cmd=cmd.replace("#SUBTYPE#",str(serie.selector_subtype))
cmd=cmd.replace("#ID#",str(serie.id))
return cmd
def addAxes(result, chartdata):
axes={
'xaxis': {
'renderer': "eval('$.jqplot.DateAxisRenderer')",
'tickRenderer': "eval('$.jqplot.CanvasAxisTickRenderer')",
'autoscale': True,
'tickOptions': {
'angle': 30
}
},
'yaxis': {
'min': 0,
'tickOptions': {}
}
}
if chartdata[0].x_numberTicks:
if result['maxseriecount']<int(chartdata[0].x_numberTicks):
axes['xaxis']['numberTicks']=result['maxseriecount']
else:
axes['xaxis']['numberTicks']=int(chartdata[0].x_numberTicks)
if chartdata[0].x_formatString:
axes['xaxis']['tickOptions']['formatString']=chartdata[0].x_formatString
if chartdata[0].y_numberTicks:
axes['yaxis']['numberTicks']=int(chartdata[0].y_numberTicks)
if chartdata[0].y_formatString:
axes['yaxis']['tickOptions']['formatString']=chartdata[0].y_formatString
else:
axes['yaxis']['tickOptions']['formatString']='%.'+str(chartdata[0].y_label_precision)+'f'
result['opt']['axes']=axes
return result
def sqlQuery(result, query, idx):
log.debug(query)
return dmdb.runQuery(query).addCallback(addResult, idx, result)
def addResult(res, idx, result):
data=[]
for l in res:
data.append([l[0].strftime("%Y-%m-%d %H:%M:%S"), l[1]])
result['data'].append(data)
if len(res) > result['maxseriecount']:
result['maxseriecount'] = len(res)
return result
def hourlySqlQuery(result, query, idx, serie):
return dmdb.runQuery(query).addCallback(hourlyResult, idx, result, serie)
def hourlyResult(res, idx, result, serie):
from datetime import datetime
today=datetime.strftime(datetime.now(), '%Y-%m-%d')
hournow=int(datetime.strftime(datetime.now(), '%H'))
data=[]
for l in res:
if str(serie.selector_subtype)=='back_in_time' and today==str(l[0]):
maxh=hournow+1
else:
maxh=24
for h in xrange(0,24):
data.append([str(l[0])+" "+str(h).zfill(2)+":00AM", l[h+1] ])
result['data'].append(data)
if len(data) > result['maxseriecount']:
result['maxseriecount'] = len(data)
return result
log.debug('PARSE CHART SERIES FOR '+str(chartname))
grid_shadow=True
grid_border=True
legend_show=True
if chartdata[0].grid_shadow=='false':
grid_shadow=False
if chartdata[0].grid_border=='false':
grid_border=False
if chartdata[0].legend_show=='false':
legend_show=False
opt={ 'title': chartdata[0].title,
'legend':{
'show': legend_show,
'location': chartdata[0].legend_position,
'renderOptions': {
'placement': chartdata[0].legend_placement
}
},
'grid':{
'shadow': grid_shadow,
'drawBorder': grid_border,
'background': chartdata[0].grid_background
},
'axes':{},
'highlighter':{'show':True,'sizeAdjust': 7.5},
'cursor':{'show':False},
'series':[],
'seriesDefaults': {'rendererOptions': {'smooth':True, 'shadowAlpha': 0.1, 'fillToZero': True}}
}
result={'opt':opt, 'data':[], 'maxseriecount':0}
idx=0
callbacks=[]
for s in series:
addserie=True
if s.selector_type=='SQL':
callbacks.append([sqlQuery, s.selector_name, idx])
elif s.selector_type=='daily_sum':
query="SELECT date as 'x', SUM("
query+="+".join(['h'+str(x).zfill(2) for x in range(0,24)])
query+=") as 'y' FROM stats_history WHERE"
if str(s.selector_name).startswith('dmdomain:'):
query+=" DMDOMAIN(name, '"+parseSelectorName(str(s.selector_name).replace('dmdomain:',''), s)+"')=1"
elif str(s.selector_name).startswith('like:'):
query+=" name LIKE '"+parseSelectorName(str(s.selector_name).replace('like:',''), s)+"'"
else:
query+=" name='"+parseSelectorName(str(s.selector_name), s)+"'"
query+=getSelectorSubtype(s)
query+=" group by date"
callbacks.append([sqlQuery, query, idx])
elif s.selector_type=='hourly_sum':
query="SELECT date,"
query+=",".join(['SUM(h'+str(x).zfill(2)+") as h"+str(x).zfill(2) for x in range(0,24)])
query+=" FROM stats_history WHERE"
if str(s.selector_name).startswith('dmdomain:'):
query+=" DMDOMAIN(name, '"+parseSelectorName(str(s.selector_name).replace('dmdomain:',''), s)+"')=1"
elif str(s.selector_name).startswith('like:'):
query+=" name LIKE '"+parseSelectorName(str(s.selector_name).replace('like:',''), s)+"'"
else:
query+=" name='"+parseSelectorName(str(s.selector_name), s)+"'"
query+=getSelectorSubtype(s)
query+=" group by date"
callbacks.append([hourlySqlQuery, query, idx, s])
else:
addserie=False
if addserie:
marker_show=True
if str(s.marker_show)=='false':
marker_show=False
fill=True
if str(s.fill)=='false':
fill=False
result['opt']['series'].append({
'label': s.label,
'lineWidth': s.line_width,
'markerOptions': {
'style': s.marker_style,
'size': s.marker_size
},
'color': s.color,
'showMarker': marker_show,
'showLine': True,
'fill': fill,
'fillAndStroke': True,
'highlighter': {
'formattingString': s.highlighter_formatString
}
})
idx+=1
d=defer.succeed(result)
for c in callbacks:
d.addCallback(c[0], *c[1:])
d.addCallback(addAxes, chartdata)
return d
def getChartData(self, resdata, chartname):
if resdata and len(resdata)>0:
return dmdb.getChartSeries(chartname).addCallback(self.parseChartSeries, resdata, chartname)
return defer.fail('No chart with the name '+str(chartname))
def web_on_getChartData(self, chartname):
log.debug('GET CHART DATA FOR '+str(chartname))
return dmdb.getChartData(chartname).addCallback(self.getChartData, chartname)
def web_on_getDaemonStatus(self): def web_on_getDaemonStatus(self):
return self.daemonstatus return self.daemonstatus
...@@ -2219,8 +2418,10 @@ class domotikaService(service.Service): ...@@ -2219,8 +2418,10 @@ class domotikaService(service.Service):
return dmdb.Users.find(where=['username=?', name], limit=1) return dmdb.Users.find(where=['username=?', name], limit=1)
def web_on_updateUserData(self, username, pwd, email, dhome, mhome, tts, def web_on_updateUserData(self, username, pwd, email, dhome, mhome, tts,
lang, slide=False, webspeech='touch', speechlang='it-IT', theme='dmblack'): lang, slide=False, webspeech='touch', speechlang='it-IT',
return dmdb.updateUserData(username, pwd, email, dhome, mhome, tts, lang,slide, webspeech, speechlang, theme) theme='dmblack', leftb='hidden-sm', rightb='hidden-sm'):
return dmdb.updateUserData(username, pwd, email, dhome, mhome, tts, lang,slide,
webspeech, speechlang, theme, leftb, rightb)
def web_on_getMaxLocalTranscode(self): def web_on_getMaxLocalTranscode(self):
return int(self.config.get('media', 'localtranscode')) return int(self.config.get('media', 'localtranscode'))
......
...@@ -72,7 +72,7 @@ class DomotikaUPNP(object): ...@@ -72,7 +72,7 @@ class DomotikaUPNP(object):
descr[k] = getattr(device, k, None) descr[k] = getattr(device, k, None)
except: except:
descr[k] = 'Unknown' descr[k] = 'Unknown'
log.info('DEVICE DATA: '+str(descr)) log.debug('DEVICE DATA: '+str(descr))
if 'Network Camera' in descr['deviceType']: if 'Network Camera' in descr['deviceType']:
log.debug("FOUND A CAMERA TO ADD") log.debug("FOUND A CAMERA TO ADD")
self.core.addMediaSource(descr) self.core.addMediaSource(descr)
......
...@@ -346,7 +346,8 @@ class UserRest(RestCore): ...@@ -346,7 +346,8 @@ class UserRest(RestCore):
self.session.mind.perms.slide=res.slide self.session.mind.perms.slide=res.slide
self.session.mind.perms.webspeech=res.webspeech self.session.mind.perms.webspeech=res.webspeech
self.session.mind.perms.speechlang=res.speechlang self.session.mind.perms.speechlang=res.speechlang
self.session.mind.perms.left_bar=res.left_bar
self.session.mind.perms.right_bar=res.right_bar
return res return res
log.info('Refresh session for user '+str(self.session.mind.perms.username)) log.info('Refresh session for user '+str(self.session.mind.perms.username))
d=self.core.getUserFromName(self.session.mind.perms.username).addCallback(setUserSession) d=self.core.getUserFromName(self.session.mind.perms.username).addCallback(setUserSession)
...@@ -375,6 +376,8 @@ class UserRest(RestCore): ...@@ -375,6 +376,8 @@ class UserRest(RestCore):
webspeech="touch" webspeech="touch"
speechlang="it-IT" speechlang="it-IT"
theme='dmblack' theme='dmblack'
leftb='hidden-sm'
rightb='hidden-sm'
if 'lang' in r.keys(): if 'lang' in r.keys():
lang=r['lang'] lang=r['lang']
if 'tts' in r.keys(): if 'tts' in r.keys():
...@@ -389,10 +392,15 @@ class UserRest(RestCore): ...@@ -389,10 +392,15 @@ class UserRest(RestCore):
webspeech=r['webspeech'] webspeech=r['webspeech']
if 'speechlang' in r.keys() and r['speechlang'] in ['it-IT','it-CH','en-US','en-GB']: if 'speechlang' in r.keys() and r['speechlang'] in ['it-IT','it-CH','en-US','en-GB']:
speechlang=r['speechlang'] speechlang=r['speechlang']
if 'leftb' in r.keys() and r['leftb'] in ['all','none','visible-sm','visible-md','visible-lg','hidden-sm','hidden-md','hidden-lg']:
leftb=str(r['leftb'])
if 'rightb' in r.keys() and r['rightb'] in ['all','none','visible-sm','visible-md','visible-lg','hidden-sm','hidden-md','hidden-lg']:
rightb=str(r['rightb'])
if 'desktop_homepath' in r.keys() and 'mobile_homepath' in r.keys() and 'email' in r.keys(): if 'desktop_homepath' in r.keys() and 'mobile_homepath' in r.keys() and 'email' in r.keys():
return self.core.updateUserData(self.session.mind.perms.username, pwd, return self.core.updateUserData(self.session.mind.perms.username, pwd,
r['email'], r['desktop_homepath'], r['mobile_homepath'], r['email'], r['desktop_homepath'], r['mobile_homepath'],
tts, lang, slide, webspeech, speechlang, theme).addCallbacks(onOk, onError) tts, lang, slide, webspeech, speechlang, theme, leftb, rightb).addCallbacks(onOk, onError)
log.info('Erroneous request on update my userdata! ('+str(self.session.mind.perms.username)+')') log.info('Erroneous request on update my userdata! ('+str(self.session.mind.perms.username)+')')
return ResponseConversion(request, code=400, entity="Bad request - error in parameters") return ResponseConversion(request, code=400, entity="Bad request - error in parameters")
...@@ -477,8 +485,26 @@ class RelayRest(RestCore): ...@@ -477,8 +485,26 @@ class RelayRest(RestCore):
return self.callbackResponse(self.core.setRelayById(rid, 'change'), request) return self.callbackResponse(self.core.setRelayById(rid, 'change'), request)
class ChartRest(RestCore):
path="charts"
@route("/", (Http.GET))
@wrapResponse
def charts(self, request, *a, **kw):
return ResponseConversion(request, code=404, entity="Not yet implemented")
@route("/chartbyid/<int:cid>", (Http.GET))
@wrapResponse
def chartById(self, request, cid, *a, **kw):
return ResponseConversion(request, code=404, entity="Not yet implemented (chart by id)")
@route("/chartbyname/<chartname>", (Http.GET))
@wrapResponse
def chartByName(self, request, chartname, *a, **kw):
return self.callbackResponse(self.core.getChartData(chartname), request)
RESTv12LIST=( RESTv12LIST=(
UserRest, UserRest,
...@@ -488,6 +514,7 @@ RESTv12LIST=( ...@@ -488,6 +514,7 @@ RESTv12LIST=(
ActionRest, ActionRest,
NotifyRest, NotifyRest,
RelayRest, RelayRest,
ChartRest,
) )
......
...@@ -249,7 +249,8 @@ class RootPage(rend.Page): ...@@ -249,7 +249,8 @@ class RootPage(rend.Page):
if headers.hasHeader("DMSESSION"): if headers.hasHeader("DMSESSION"):
headers.removeHeader("DMSESSION") headers.removeHeader("DMSESSION")
headervalue = str(session.uid) headervalue = str(session.uid)
cols=['username','passwd','id','homepath','email','tts','language','slide','webspeech','speechlang','gui_theme'] cols=['username','passwd','id','homepath','email','tts','language','slide',
'webspeech','speechlang','gui_theme', 'left_bar','right_bar']
try: try:
headervalue = session.mind.perms.toHash(cols) headervalue = session.mind.perms.toHash(cols)
except: except:
...@@ -265,6 +266,8 @@ class RootPage(rend.Page): ...@@ -265,6 +266,8 @@ class RootPage(rend.Page):
headervalue['webspeech'] = 'touch' headervalue['webspeech'] = 'touch'
headervalue['speechlang'] = 'it-IT' headervalue['speechlang'] = 'it-IT'
headervalue['gui_theme' ] = 'dmblack' headervalue['gui_theme' ] = 'dmblack'
headervalue['left_bar' ] = 'hidden-sm'
headervalue['right_bar' ] = 'hidden-sm'
headervalue['sessionid'] = session.uid headervalue['sessionid'] = session.uid
headervalue['logged'] = self.logged headervalue['logged'] = self.logged
log.debug('DMSESSION SEND '+str(headervalue)) log.debug('DMSESSION SEND '+str(headervalue))
......
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