diff --git a/assets/js/co.js b/assets/js/co.js index dad433b5..9ecce4e7 100644 --- a/assets/js/co.js +++ b/assets/js/co.js @@ -618,6 +618,14 @@ var urlCtrl = { "#define." : {title:'TAG MAP ', icon : 'map-marker', action:function( hash ){ showDefinition("explain"+hash.split('.')[1]) } }, "#data.index" : {title:'OPEN DATA FOR ALL', icon : 'fa-folder-open-o'}, "#opendata" : {"alias":"#data.index"}, + "#thing.graph" : {title:'GRAPH IOT', icon : 'fa-line-chart'}, + "#thing.manage" : {title:'MANAGE IOT', icon : 'fa-database'}, + "#thing.updatesckdevices" : {title:'UPDATE SCK', icon : 'fa-database'}, + "#thing.scklastestreadings" : {title:'LASTEST READING SCK', icon : 'fa-database'}, + "#thing.getsckdataincodb" : {title:'DATA RECORD SCK', icon : 'fa-database'}, + "#thing.synthetizesckdata" : {title:'SYNTHETIZE RECORD SCK', icon : 'fa-database'}, + "#search" : { "title":'SEARCH AND FIND', "icon" : 'map-search', "hash" : "#default.directory", "preaction":function( hash ){ return searchByHash(hash);} }, + }, shortVal : ["p","poi","s","o","e","pr","c","cl"/* "s","v","a", "r",*/], shortKey : [ "citoyens","poi" ,"siteurl","organizations","events","projects" ,"cities" ,"classified"/*"entry","vote" ,"action" ,"rooms" */], diff --git a/assets/js/sig/map_initializer.js b/assets/js/sig/map_initializer.js index bf148de0..ed3e69d2 100755 --- a/assets/js/sig/map_initializer.js +++ b/assets/js/sig/map_initializer.js @@ -337,6 +337,7 @@ "poi.openScene" : "poi-marker-default", "poi.stand" : "poi-marker-default", "poi.parking" : "poi-marker-default", + "poi.smartCitizen" : "poi-marker-default", "entry" : "entry-marker-default", "action" : "action-marker-default", diff --git a/assets/js/thing/graph.js b/assets/js/thing/graph.js new file mode 100644 index 00000000..90a86eb2 --- /dev/null +++ b/assets/js/thing/graph.js @@ -0,0 +1,313 @@ +/** +*@author: Danzal +* +*/ +function showAllGraph(){ $(".graphs").show(); } +function showGraph(figGraph){ $("#"+figGraph).show(); } +function hideAllGraph(){ $(".graphs").hide(); } +function hideGraph(figGraph){ $("#"+figGraph).hide(); } + +function hideAllChart(sourcedb){ $(".chart_"+sourcedb).hide(); } +function showAllChart(sourcedb){ $(".chart_"+sourcedb).show(); } + +function showHideChart(valuebtn){ + //var sourcedb = $(this).data("sourcedb") ; // amélioration pour un eselection direct + var sourceText=""; + var toShow=""; + switch (valuebtn) { + case 0 : + if(!graphReady.dCOdb){ + sourceText="la base de données de Communecter"; + setGraphFromCoDB(); + } + hideAllChart("dAPIsc"); + toShow="dCOdb"; + break; + case 1: + if(!graphReady.dAPIsc){ + sourceText="l'API de smartcitizen"; + setGraphFromAPIsmartcitizen(); + } + hideAllChart("dCOdb"); + toShow="dAPIsc"; + break; + /*case 2: + //TODO : redrawBothChartGraph(); + showAllChart("dCOdb"); + showAllChart("dAPIsc"); + break;*/ + } + if((!graphReady.dCOdb && valuebtn==0) || ( !graphReady.dAPIsc && valuebtn==1) ){ + $.blockUI({ message : '<span class="homestead"><i class="fa fa-spinner fa-circle-o-noch"></i> Chargement des données depuis '+sourceText+' en cours ... </span>' }); + }else{ + graphesRedraw(toShow); + } + showAllChart(toShow); + $("#btnTempAndHum").click(); + $("#legend-graph").removeClass("hidden"); + +} + +function setSVGForSensor(sensor,sensorKey) { + + var svgId = "sensor"+sensor; + var figGraph = "graphe_"+sensor; + var gId = svgId+"_g"; + + var svgObj = d3.select("#"+figGraph) + .append("svg").attr("width",svgwidth).attr("height",svgheight) + .attr("viewBox","0 0 "+svgwidth+" "+svgheight) + .attr("preserveAspectRatio","xMidYMid meet") + .attr("class","col-sm-12 svggraph") + .attr("id", svgId); + + var g = svgObj + .append("g") + .attr("transform", "translate(" + gmargin.left + "," + gmargin.top + ")") + .attr("id", gId); + + var captionSensor = d3.select("#"+figGraph) + .append("figcaption") + .text("Graph of sensor "+infoSensors[svgId].name+" ("+infoSensors[svgId].description+")"); + + multiGraphe[sensorKey] = {svgid : svgId, + svg : svgObj, + mesure : {description : "", unit : "" }, + dimension : { width : +gwidth, + height : +gheight, + margin : gmargin }, + gid : gId , + domain : {Yn : null, Ym : null, Xn : vXn, Xm : vXm , xDomainInitialized : false}, + data : {}, + divgraphid : figGraph, + urlReqApi : "" + }; + + mylog.log('multiGraphe['+sensorKey+'] : '); + mylog.log(multiGraphe[sensorKey]); +} + +function setLegend(deviceId,strkCol){ + + var idIM = 'icnmin_'+deviceId; + var idTL = 'textdevice_'+deviceId; + + var legendILSC="<a href='https://smartcitizen.me/kits/"+deviceId+"' target='_blank'><i class='fa fa-minus' id='"+idIM+"' style='color:"+strkCol+";'></i> SCK device "+deviceId+"</a>"; + // var iconMinus = "<i class='fa fa-minus' id='"+idIM+"' style='color:"+strkCol+";'></i>"; + var dLegend = d3.select("#legend").append("div").attr("id","legend_"+deviceId).attr("class","col-sm-12 col-xs-12"); + dLegend.append("span").html(legendILSC); +} + +function setStrokeColorAndLegendForDevice(device) { + //var stId = "sCol_"+device; + if(strockeColorArray[device] == null ){ + var strockeColor = "rgb("+Math.floor((Math.random()*220)+1)+","+Math.floor((Math.random()*220)+1)+","+Math.floor((Math.random()*220)+1)+")"; + strockeColorArray[device]=strockeColor; + setLegend(device,strockeColor); + } + //return strockeColor; +} + +function setGraphDomain(data, sensorkey,redraw){ + mylog.log("setGraphDomain"); +if(redraw==true){ + multiGraphe[sensorkey].domain.Yn == null; + multiGraphe[sensorkey].domain.Ym == null; + min[sensorkey]=null; + max[sensorkey]=null; +} + + for(id in data){ + var dDS = data[id][sensorkey]; + //mylog.log("dDS : " ); + //mylog.log(dDS); + if(dDS.length>=1){ + min[sensorkey]=d3.min( dDS, function(d){ return d.values;}); + max[sensorkey]=d3.max( dDS, function(d){ return d.values;}); + //mylog.log("- sensorkey :"+ sensorkey+ ": min : "+ min +" -- max: "+max); + if (multiGraphe[sensorkey].domain.Yn == null || multiGraphe[sensorkey].domain.Yn > min[sensorkey]) { + multiGraphe[sensorkey].domain.Yn = min[sensorkey]; + //mylog.log("multiGraphe["+sensorkey+"].domain.Yn : " + multiGraphe[sensorkey].domain.Yn); + } + if (multiGraphe[sensorkey].domain.Ym == null || multiGraphe[sensorkey].domain.Ym < max[sensorkey]) { + multiGraphe[sensorkey].domain.Ym = max[sensorkey]; + //mylog.log("multiGraphe["+sensorkey+"].domain.Ym : "+multiGraphe[sensorkey].domain.Ym); + } + } + } +} + + +function setAxisXY(sensorKey){ + setAxisX(sensorKey); + setAxisY(sensorKey); +} + + +function setAxisX(sensorKey){ + mylog.log(" --- setAxisX --- "); + var gId = multiGraphe[sensorKey].gid; + var g = d3.select("#"+gId); + var xAxisId="xAxis"+multiGraphe[sensorKey].svgid; + //var height = multiGraphe[sensorKey].dimension.height; + + d3.select("#"+xAxisId).remove(); // TODO refaire la selection sur le graphe sensor + + g.append("g") + .attr("id", xAxisId) + .attr("class", "theAxis") + .attr("transform", "translate(0," + gheight + ")") + .call(d3.axisBottom(x)) + /// * + //.append("text") + //.attr("fill","#000") + //.attr("x", gwidth) + //.attr("text-anchor","end") + //.text("time") + ; +} + +function setAxisY(sensorKey){ + mylog.log(" --- setAxisY --- "); + + var gId = multiGraphe[sensorKey].gid; + var g = d3.select("#"+gId); + var yAxisId="yAxis"+ multiGraphe[sensorKey].svgid; + + d3.select("#"+yAxisId).remove(); // TODO refaire la selection sur le graphe sensor + + var sensorkunit = sensorKey+" "+infoSensors[multiGraphe[sensorKey].svgid].unit ; // mettre dans le text + + g.append("g") + .attr("id", yAxisId) + .attr("class", "theAxis") + .call(d3.axisLeft(y)) + .append("text") + .attr("fill","#000") + .attr("transform", "rotate(-90)") + .attr("y", 8) + .attr("dy", "0.71em") + .attr("text-anchor","end") + .text(sensorkunit) + ; + +} + +function tracer(da,device,sensorKey,strokeColor="blue",source, strokeWidth=1.5){ + mylog.log("da in tracer"); + mylog.log(da); + if (da.length>0){ + mylog.log("----------- da.length > 0 : tracer ! -------- "); + mylog.log("-- tracer - device : "+device+" sensor "+sensorKey); + var g = d3.select("#"+multiGraphe[sensorKey].gid); + + var gpathId = source+"_gpId_"+device+multiGraphe[sensorKey].svgid; //ex : [source]_gpId_4162sensor17 + var graphClassSensor = "gcs_"+dataSensors[sensorKey].id+" "+source+" chart_"+source+" "+device +" chart_graph" ; + g.append("path") + .datum(da) + .attr("fill", "none") + .attr("class", graphClassSensor) + .attr("id", gpathId) + .attr("stroke", strokeColor) + .attr("stroke-linejoin", "round") + .attr("stroke-linecap", "round") + .attr("stroke-width", strokeWidth) + .attr("d", line); + /* TODO afficher text du device lors d'un survol avec la souris + g.append("text") + .datum(function(d){ return {value: d.values[d.values.length - 1]}; }) + .attr("transform", function(d) { return "translate(" + x(d.values) + "," + y(d.timestamps) + ")"; }) + .attr("x", 3) + .attr("dy", "0.35em") + .style("font", "10px sans-serif") + .text(function(d) { return d.values; });*/ + } + $.unblockUI(); + +} + +function graphesRedraw(source){ + for(keySens in multiGraphe){ + grapheOneSensor(keySens,source, true); + } +} + +function grapheOneSensor(keySens,source, redraw) { + $.unblockUI(); + var data = (source=="dCOdb")? dCOdb : dAPIsc; + + setGraphDomain(data, keySens, redraw); +//TODO Prendre un domaine 10% plus grand que les data en Y 5%top et 5 bottom + y.domain([(multiGraphe[keySens].domain.Yn-1), (multiGraphe[keySens].domain.Ym+1)]); + setAxisY(keySens); + + if(multiGraphe[keySens].domain.xDomainInitialized==false || redraw==true){ + x.domain([multiGraphe[keySens].domain.Xn, multiGraphe[keySens].domain.Xm]); + setAxisX(keySens); + multiGraphe[keySens].domain.xDomainInitialized=true; + } + + if(redraw==false){ + for (dId in data){ + tracer(data[dId][keySens], dId, keySens, strockeColorArray[dId],source); + } + } + if(graphReady[source]==false){ + $(".svggraph").show(); + $("#legend-graph").show(); + graphReady[source]=true; + } +} + +function fillArrayWithObjectTimestampsAndValues(readings, deviceid, sensorkey){ + mylog.log("- fillArrayWithObjectTimestampsAndValues - "); + + dAPIsc[deviceid][sensorkey] = readings.map( + function(item){ + var ts = new Date(); + ts.setTime(Date.parse(item[0])); + ts.setSeconds(0); + item[1] = +item[1]; + return {timestamps : ts, values : item[1]}; + } + ); + //multiGraphe[sensorkey].data[deviceid] = dAPIsc[deviceid][sensorkey]; +} + +function dataSensorAdaptorTimestampsAndValues(convertedDataRecord,device){ + mylog.log("--dataSensorAdaptorTimestampsAndValues--"); + var dataCOdb={temp : [], hum : [], bat: [], panel : [], no2 : [], panel : [], co : [], noise : [], nets : [], light : []}; + convertedDataRecord.forEach( function(item){ + var ts = new Date(); + ts.setTime(Date.parse(item.timestamp)); + ts.setSeconds(0); + + item.temp =+item.temp; + item.hum =+item.hum; + item.bat =+item.bat; + item.panel=+item.panel; + item.co =+item.co; + item.no2 =+item.no2; + item.light=+item.light; + item.nets =+item.nets; + item.noise=+item.noise; + + dataCOdb.temp.push({timestamps : ts, values : item.temp}); + dataCOdb.hum.push({timestamps : ts, values : item.hum}); + dataCOdb.bat.push({timestamps : ts, values : item.bat}); + dataCOdb.panel.push({timestamps : ts, values : item.panel}); + dataCOdb.no2.push({timestamps : ts, values : item.no2}); + dataCOdb.co.push({timestamps : ts, values : item.co}); + dataCOdb.noise.push({timestamps : ts, values : item.noise}); + dataCOdb.nets.push({timestamps : ts, values : item.nets}); + dataCOdb.light.push({timestamps : ts, values : item.light}); + + } + ); + dCOdb[device]=dataCOdb; + + for (ks in multiGraphe){ + multiGraphe[ks].data[device]=dataCOdb[ks]; + } + //return dataCOdb; +} diff --git a/components/CommunecterController.php b/components/CommunecterController.php index 024492cb..e4b2dec5 100755 --- a/components/CommunecterController.php +++ b/components/CommunecterController.php @@ -485,10 +485,20 @@ class CommunecterController extends Controller "checkurlexists" => array('href' => "/ph/communecter/app/checkurlexists", "public" => true), "rooms" => array('href' => "/ph/communecter/app/rooms", "public" => true), "survey" => array('href' => "/ph/communecter/app/survey", "public" => true), + "thing" => array('href' => "/ph/communecter/app/thing", "public" => true), ), "siteurl" => array( "incnbclick" => array('href' => "ph/communecter/siteurl/incnbclick") ), + "thing" => array( + //"index" => array('href' => "/ph/communecter/thing/index", "public" => true ), + "graph" => array('href' => "/ph/communecter/thing/graph", "public" => true ), + "scklastestreadings" => array('href' => "/ph/communecter/thing/scklastestreadings", "public" => true ), + "updatesckdevices" => array('href' => "/ph/communecter/thing/updatesckdevices", "public" => true ), + "manage" => array('href' => "/ph/communecter/thing/manage","public"=>true), + "getsckdataincodb" => array('href' => "/ph/communecter/thing/getsckdataincodb","public"=>true), + "synthetizesckdata" => array('href' => "/ph/communecter/thing/synthetizesckdata","public"=>true), + ), ); function initPage(){ diff --git a/config/CO2/params.json b/config/CO2/params.json index 279aedf2..d637ec54 100644 --- a/config/CO2/params.json +++ b/config/CO2/params.json @@ -175,7 +175,19 @@ "icon" : "university", "mainTitle" : "Partie Admin Public", "placeholderMainSearch" : "Admin Public ..." - } + }, + + "#thing": { + "inMenu" : true, + "useHeader" : false, + "open" : true, + "subdomain" : "thing", + "subdomainName" : "Objets communectés", + "hash" : "#app.thing", + "icon" : "database", + "mainTitle" : "Les objets communectés", + "placeholderMainSearch" : "Les objets communectés ..." + } } diff --git a/config/CO2/thing.json b/config/CO2/thing.json new file mode 100644 index 00000000..69b28b30 --- /dev/null +++ b/config/CO2/thing.json @@ -0,0 +1,58 @@ +{ + "sections" : { + "smartcitizen" : { + "label":"Smart-Citizen-Kit", + "labelshort" : "SCK", + "key" : "smartCitizen", + "icon" : "thermometer-three-quarters", + "section":1, + "color":"azure", + "filter" : "sckFilters", + "active" : true + + }, + "CO PI": { + "label":"CO PI", + "key" : "copi", + "icon" : "clone", + "section":2, + "color":"azure", + "filter" : "copiFilters", + "active": false + } + }, + "sckFilters": { + "Dernieres-Mesures" : { + "page" : "scklastestreadings", + "label" :"Dernières Mesures", + "icon" : "clock-o", + "key" : "smartCitizen", + "subcat" : [ "Temperature et humidité" , "Gaz", "Lumière" , "Bruit" , "Nets", "Énergie", "Tous" ] + }, + "Graphes" : { + "page" : "graph", + "icon" : "line-chart", + "label" :"Graphes", + "key" : "smartCitizen", + "subcat" : [ "Données Communecter", "Données API SmartCitizen" ] + }, + "Gestion-SCK" : { + "page" : "manage", + "icon" : "database", + "label" :"Gestion SCK", + "key" : "smartCitizen", + "forAdmin" : true, + "subcat" : [ "Avec compte smartcitizen", "Sans compte smartcitizen" ] + } + }, + "copiFilters": { + "Voir-tous" : { + "page": "copi", + "icon" : "cloud", + "label" :"Copi All", + "key" : "copi", + "subcat" : [ ] + } + } + +} \ No newline at end of file diff --git a/controllers/AppController.php b/controllers/AppController.php index 1d04200a..19227b45 100755 --- a/controllers/AppController.php +++ b/controllers/AppController.php @@ -348,5 +348,8 @@ function leftShift32($number, $steps) { exit; } - + public function actionThing(){ + CO2Stat::incNbLoad("co2-thing"); + echo $this->renderPartial("thing",array(), true); + } } \ No newline at end of file diff --git a/controllers/ThingController.php b/controllers/ThingController.php new file mode 100644 index 00000000..de2d3910 --- /dev/null +++ b/controllers/ThingController.php @@ -0,0 +1,30 @@ +<?php +/** +* Created on examples of other controllers +* +* @author: Jean Daniel CAZAL <danzalkay551@gmail.com> +* Date: 26/01/2017 rapatrié dans CO2 le 22/03/17 +*/ + +class ThingController extends CommunecterController { + + const moduleTitle = "Thing"; + protected function beforeAction($action) { + parent::initPage(); + return parent::beforeAction($action); + } + + public function actions(){ + return array( + //'index' => 'citizenToolKit.controllers.thing.IndexAction', + 'graph' => 'citizenToolKit.controllers.thing.GetGraphAction', + 'scklastestreadings' => 'citizenToolKit.controllers.thing.GetLastestReadingAction', + 'updatesckdevices' => 'citizenToolKit.controllers.thing.UpdateSckDevicesAction', + 'manage' => 'citizenToolKit.controllers.thing.ManageAction', + 'getsckdataincodb' => 'citizenToolKit.controllers.thing.GetSCKDataInCODBAction', + 'synthetizesckdata' => 'citizenToolKit.controllers.thing.SynthetizeSCKDataInCODBAction', + + ); + } + +} diff --git a/docs/bugs.org b/docs/bugs.org index 172fecf5..0dea511c 100755 --- a/docs/bugs.org +++ b/docs/bugs.org @@ -2,8 +2,8 @@ * Correction de bugs CO2 * ************************************************************ - - +[ ] agenda ajout d'evenement impossible le datepicker bloque la date de fin, même si c'est bien une date ultérieur à la date de début. +[ ] Les annonces ne s'enregistre pas si on ajoute une adresse (passage par la carte). diff --git a/docs/specs/Thing.md b/docs/specs/Thing.md new file mode 100644 index 00000000..329fa43e --- /dev/null +++ b/docs/specs/Thing.md @@ -0,0 +1,65 @@ +# Thing +Au delà des Smart-Citizen-Kit, thing pourrrait permettre d'intégrer les objets connecté à CO2, COPI. + +Un point d'entrée est disponible à coté du bouton "actus", il est nommé "Objets communectés" (on peut renommer en IoT), l'icone est un database. + +## Smart-Citizen-Kit +La view index permet d'accéder + * à deux vue différentre : + * Les graphes (encore du developpement à finir) + * Les dernières valeurs enregistrés + * à une page de gestion (travaux en cours): + * première fonctionnalité de la page ajouter l'adresse mac correspondant au device (en cours de finalisation) + +### Double push + +Le kit pourrait être utilisé exclusivement avec Communecter, un serveur de temps pour sck est ajouter dans l'API, la reception simple fonctionne déjà, et la réception batch (plusieurs enregistrements en même temps) est en cours de développement. Ces fonctionnalités peuvent permettre une redondance, si on développe tous les fonctions nécessaire. + +#### Firmware +Le firmware sck double push a été développé par Nicolas Grondin en s'inspirant des débuts de travaux de Jean Daniel CAZAL (Stagiaire). +Nicolas Grondin a par la suite amélioré la gestion de la FIFO (écriture et lecture en EEPROM) et la stabilité du firmware. +Avec le double push nous devons choisir une période d'envoi des enregistrements adéquat pour ne pas surcharger la base de données, pour l'instant ce "time update" est de 5 minutes (300 secondes). + +#### Coté serveur +Un outil datetime dans l'API de communecter, permet de fournir l'heure au SCK. +Pour les enregistrements on passe par element/save, avec un traitement grace au fonction dans le model thing. + + +### Graphe (#thing.graph) + +Les données sont récupérer via l'API de Smartcitizen (api.smartcitizen.me/v0), la version de l'api est succeptible de changer, il faudra alors changer la constante Thing::URL_API_SC. +Les devices possèdent 9 sensors, pour obtenir les enregistrements (Température, Humidité, CO, NO2, Lumière, Bruit, Nombre de réseaux WLAN environnant, Batterie, et Panneau Photo-Voltaïque). +Le nombre de réseaux WIFI environnant n'est pas utilisé. + +#### Les requetes sur l'API + +Il faut faire une requete par sensor avec un rollup (temps séparant 2 enregistrement), une date de début et une date de fin. +La date de fin est l'heure actuelle en GMT. +La date de début est calculer, si le paramètre nbDays est utilisé dans la requète pour afficher la page graphe (par exemple : #thing.graphe?nbDays=20 , il y a une limite à 31 jours), sinon c'est un graphe sur une journée. C'est une fonctionnalité de substitution aux datepickers. + + +La page graphe utilise D3.js pour construire les graphes. Chaque sensor a son SVG dédié, si plusieurs devices sont dans la même zone, les données sont afficher sur le mème graphe. Pour l'instant la zone c'est même code postale et même country, on devra faire un filtrage par niveau par la suite (Région département). + +#### Bouton de selection de graphe +Tous les graphes sont construit une seul fois au chargement de la page. Les boutons cache les graphes et montre ceux qui sont selectionnés, le dernier bouton affiche tous les graphes. + +#### Légende +La légende permet d'être redirigé vers le device sur site officiel des SCK : smartcitizen.me/kits/[deviceId] + + +### Page des dernières valeur enregistré +Affiche les dernièrs enregistrement du SCK. + +Fonctionnalité qui pourra permettre d'ajouter valeurs dans des POD. + + +### Page de gestion (#thing.manage) + +Cette page à pour but de faire la liaison entre les enregistrements reçu dans notre base, et le device qui les envois. En effet, les devices n'ont pas connaissance de leur deviceId. Sur smartcitizen, cette liaison est faite lors de l'enregistrement du kit sur la plateforme. +Nous avons besoin de la même liaison dans notre base de données, celà permet au utilisateurs ou nous même (si on limite l'accès au administrateurs) de renseigné l'adresse mac du kit. + + +### Base de données + +[Une estimation de la capacité nécessaire](https://docs.google.com/spreadsheets/d/1E5_lm-dEw28Vq176nwduC9KgFOfZzYbgjU2mWfJxYRo/edit?usp=sharing) + diff --git a/views/app/annonces.php b/views/app/annonces.php index fee6afdc..aa07a20e 100755 --- a/views/app/annonces.php +++ b/views/app/annonces.php @@ -21,7 +21,7 @@ $this->renderPartial($layoutPath.'header', array( "layoutPath"=>$layoutPath , "type" => @$type, - "page" => page) ); + "page" => $page) ); ?> <style> diff --git a/views/app/thing.php b/views/app/thing.php new file mode 100644 index 00000000..80ffc26d --- /dev/null +++ b/views/app/thing.php @@ -0,0 +1,327 @@ +<?php +$cs = Yii::app()->getClientScript(); +//HtmlHelper::registerCssAndScriptsFiles( $cssAnsScriptFilesModule ,Yii::app()->request->baseUrl); + +$layoutPath = 'webroot.themes.'.Yii::app()->theme->name.'.views.layouts.'; + //header + menu + $this->renderPartial($layoutPath.'header', + array( "layoutPath"=>$layoutPath, + "page" => "thing") ); + +//tu auras "states":true si ta communexion est activée +//pour récupérer les valeurs de communexion tu a juste à faire ça : CO2::getCommunexionCookies(); +// $boardIds = Thing::getDistinctSCK("boardId"); +// $deviceIds= Thing::getDistinctSCK("deviceId"); + +$communexion = CO2::getCommunexionCookies(); +//TODO : utiliser pour eviter l'utilisation à chaque page + /* if($communexion["state"] == false){ + //$postalCode= " " ; + }else{ + //$postalCode=$cpCommunexion; + } +*/ +$this->renderPartial($layoutPath.'breadcrum_communexion', array("type"=>@$type)); +?> +<style> + +.main-container{ + margin-top: 40px; + padding-top: 40px; + +} +#sub-menu-left{ + margin-top:1px; + /*text-align: left;*/ +} +#sub-menu-left .btn{ + /*background-color: #4285f4; + border-color: #4285f4;*/ + /*color:white;*/ + /*border-radius:80px;*/ + font-weight: 700; +} +#sub-menu-left.subsub .btn{ + width:95%; + text-align: left; + background-color: white; + border-color: white; + color:#4285f4; +} +#sub-menu-left.subsub{ + min-width: 180px; +} +#page #dropdown_thing{ + min-height:500px; + /*margin-top:30px;*/ +} +#page .row.headerDirectory{ + margin-top: 20px; + display: none; +} +#page p { + font-size: 13px; +} +.breadcrum-communexion{ + margin-top:25px; +} + +.breadcrum-communexion .item-globalscope-checker{ + border-bottom:1px solid #e6344d; +} +.item-globalscope-checker.inactive{ + color:#DBBCC1 !important; + border-bottom:0px; + margin(top:-6px;) +} +.item-globalscope-checker:hover, +.item-globalscope-checker:active, +.item-globalscope-checker:focus{ + color:#e6344d !important; + border-bottom:1px solid #e6344d; + text-decoration: none !important; +} + +.keycat:hover, +.keycat.active, +.btn-select-category-1:hover, +.btn-select-category-1.active{ + background-color: #2C3E50!important; + color: #fff!important; + border-color:transparent!important; +} + + +</style> + +<div class="col-md-12 col-sm-12 col-xs-12 container bg-white no-padding shadow" id="content-thing" style="min-height:700px;"> + + <div class="padding-5" id="page"> + <?php $thing = CO2::getContextList("thing"); ?> + + <div id="menu-section-thing" class="row col-xs-12 col-md-12 col-sm-12 text-center subsub"> + <h4 class="padding-10 letter-azure label-category col-md-3 col-sm-3 hidden-xs" id="title-menu-section"> + <i class="fa fa-object-group"></i> <span id="title-sub-thing">Objets CO2 </span> + </h4> + <?php + $currentSection = 1; + foreach ($thing["sections"] as $key => $section) { + if(isset($section['active']) && $section['active']==true){ + ?> + <div class="col-md-3 col-sm-4 col-xs-6 no-padding"> + <button class="btn btn-default col-md-12 col-sm-12 padding-10 bold text-dark elipsis btn-select-type-anc" id="btn-thing-section-<?php echo @$section["key"]; ?>" + data-type-anc="<?php echo @$section["label"]; ?>" data-key="<?php echo @$section["key"]; ?>" data-type="thing" + style="border-radius:0px; border-color: transparent; text-transform: uppercase;"> + <i class="fa fa-<?php echo @$section["icon"]; ?> fa-2x"></i> <span class=""><?php echo @$section["label"]; ?></span> + </button> + </div> + <?php } + } ?> + <hr class="col-md-12 col-sm-12 col-xs-12 no-padding" id="before-section-result"> + </div> + <div class="row "> + <div class="col-md-3 col-sm-3 col-xs-12 margin-top-15 text-right subsub thingFilters" id="sub-menu-left"> + <?php + //$thing = CO2::getContextList("thing"); + foreach ($thing as $key1 => $filters) { + if(strpos($key1,"Filters")!=false){ + if (is_array($filters)) { + foreach ($filters as $key => $action) { + if( ( empty($action["forAdmin"]) || $action["forAdmin"] != true || ( $action["forAdmin"]==true && Role::isSuperAdmin(Role::getRolesUserId(Yii::app()->session["userId"]) ) ) ) && is_array($action) ) { ?> + <button class="btn btn-default text-dark margin-bottom-5 btn-select-category-1 hidden btn-select-<?php echo @$action["key"]; ?>" style="margin-left:-5px;" data-keycat="<?php echo $key; ?>" data-section="<?php echo @$action["key"]; ?>" data-page="<?php echo @$action["page"]; ?>"> + <i class="fa fa-<?php echo @$action["icon"]; ?>"></i> <?php echo $action['label']; ?> + </button> + <div id="menu-keycat-<?php echo @$action["page"]; ?>" > + <?php foreach ($action["subcat"] as $key2 => $action2) { ?> + <button class="btn btn-default text-dark margin-bottom-5 margin-left-15 hidden keycat keycat-<?php echo $key; ?> btn-<?php echo @$action["key"]; ?>" data-categ="<?php echo $key; ?>" data-key="<?php echo @$action["key"]; ?>" data-key2="<?php echo $key2; ?>"> + <i class="fa fa-angle-right"></i> <?php echo $action2; ?> + </button><br class="hidden"> + <?php } ?> + </div> + <?php + } + } + } + } + } ?> + </div> + <div class="col-sm-9 col-md-9 col-xs-12 " id="dropdown_thing"></div> + </div> + </div> +</div> + +<?php $this->renderPartial($layoutPath.'footer', array("subdomain"=>"thing")); ?> + +<script> +/*----------------------------- */ +var alReady=false; +var section = ""; +var classType = ""; +var classSubType = ""; +var pageReady=false; +var section=""; +var sectionKey=""; + +var smartCitizenSelector = { + "Dernieres-Mesures" : [ "lastreading", [ "all" , "temp" , "hum" , "light" , "co" , "no2" , "noise" , "nets", "bat" , "pv" ]], + "Graphes" : [".chart_graph",[ ".dCOdb", ".dAPIsc" ]], + "Gestion-SCK" :[ "sck-maj",[ "sck-maj-principal", "sck-maj-secondaire" ]] +}; + +jQuery(document).ready(function() { + initKInterface({"affixTop":0}); + bindLeftMenuFilters(); + //active premiere section : + activeFirst("menu-section-thing","btn-select-type-anc"); + //active premiere page + //activeFirst( "sub-menu-left", "btn-select-category-1"); + //communexion=<?php //echo json_encode($communexion); ?>; + /*var postalCode=<?php //echo $postalCode ?>; + mylog.log("communexion postalCode : "); + mylog.log(postalCode);*/ + setTitle("Objets communectés","fa-database"); + + }); + +function getpageSCK(viewsThing){ + + $.ajax({ + type: "GET", + url: baseUrl+'/'+moduleId+"/thing/"+viewsThing, + success:function(data){ + alReady=true; + setTimeout(function(){ alReady=false; }, 2000 ); + $("#dropdown_thing").html(data); + }, + error:function(data){ mylog.log("Error : ajax not success"); + mylog.log(data); } + }).done(function(){ + pageReady=true; + activeFirst("menu-keycat-"+viewsThing,"keycat" ); + }); +} + +function getpageCOPI(viewsCopi){ + //todo pour les CO-PI ; + $("#dropdown_thing").html("<h3> COPI (Vide actuellement) <h3> <p> Ici vous avez accès aux pages concernant les COPIs <p> "); +} + +function bindLeftMenuFilters () { + + $(".btn-select-type-anc").off().on("click", function(){ + section = $(this).data("type-anc"); + sectionKey = $(this).data("key"); + + $(".btn-select-type-anc, .btn-select-category-1, .keycat").removeClass("active"); + $(".keycat").addClass("hidden"); + $(".btn-select-category-1").addClass("hidden"); + $(".btn-select-"+sectionKey).removeClass("hidden"); + $(this).addClass("active"); + + KScrollTo("#dropdown_thing"); + + if( sectionKey == "smartCitizen"){ + $("#dropdown_thing").html("<h3> Smart-Citizen-Kit<h3> <p>Ici vous avez accès aux pages concernant les kits déclarés dans Communecter<p> "); + }else{ + $("#dropdown_thing").html("<h3> COPI (Vide actuellement) <h3> <p> Ici vous avez accès au pages concernant les COPIs <p> "); + } + //active le premier bouton de la page + }); + + $(".btn-select-category-1").off().on("click", function(){ + if (alReady==false) { + $(".btn-select-category-1").removeClass("active"); + $(this).addClass("active"); + + classType = $(this).data("keycat"); + var page = $(this).data("page"); + sectionKey = $(this).data("section"); + $("#title-menu-section").text(classType); + + $(".keycat").addClass("hidden"); + $(".keycat").removeClass("active"); + $(".keycat-"+classType).removeClass("hidden"); + + if(sectionKey=="smartCitizen") { + getpageSCK(page); + }else{ + getpageCOPI(page); + } + } + }); + + $(".keycat").off().on("click", function(){ + + $(".keycat").removeClass("active"); + $(this).addClass("active"); + var classSubType = $(this).data("keycat"); + + classType = $(this).data("categ"); + var key2 = $(this).data("key2"); + mylog.log('classType : '+classType+' classSubType : '+classSubType+' key2 :'+key2); + + var toShow = smartCitizenSelector[classType][1][key2]; + var toHide = smartCitizenSelector[classType][0]; + + if(classType=="Gestion-SCK"){ + $("."+toHide).addClass('hidden'); + $("#"+toShow).removeClass('hidden'); + }else if (classType=="Dernieres-Mesures") { + keycatButton(classType, key2); // pour la page dernière mesure + } else if(classType=="Graphes"){ + showHideChart(key2); + } + }); +} + +function activeFirst(inDivID,classToActivate ){ + var divWithBtn=document.getElementById(inDivID); + divWithBtn.querySelector("."+classToActivate).click(); +} + +// Fonctions pour cacher et montrer +function showAllReading(){ $(".reading").removeClass("hidden"); } + +function showReading(divReading){ $("#"+divReading).removeClass("hidden"); } + +function hideAllReading(){ $(".reading").addClass("hidden"); } + +function hideReading(divReading){ $("#"+divReading).addClass("hidden"); } + +function keycatButton (classType, value){ + hideAllReading(); + //$(".reading").addClass("hidden"); + //$(".reading").hide(); + var list=[]; + switch(value) { + case 0: //temp et hum + list.push(12,13); + break; + case 1: //co no2 + list.push(15,16); + break; + case 2: //lum + list.push(14); + break; + case 3: //bruit + list.push(7); + break; + case 4: // nets + list.push(21); + break; + case 5: //energie : batt et solarPV + list.push(17,18); + break; + case 6: + showAllReading(); + break; + } + for(var s=0;s<list.length; s++){ + var divReading = "sensor-"+list[s]; + showReading(divReading); + //$("#"+divReading).removeClass("hidden"); + //$("#"+divReading).show(); + } +} + +</script> \ No newline at end of file diff --git a/views/thing/graph.php b/views/thing/graph.php new file mode 100644 index 00000000..14e25c54 --- /dev/null +++ b/views/thing/graph.php @@ -0,0 +1,562 @@ +<?php + +$cssAnsScriptFiles = array( + //'/plugins/d3/d3.v3.min.js', + //'/plugins/d3/c3.min.js', + //'/plugins/d3/c3.min.css', + '/plugins/d3/d3.v4.min.js' + ); +HtmlHelper::registerCssAndScriptsFiles($cssAnsScriptFiles, Yii::app()->request->baseUrl); + +$cssAnsScriptFilesModule = array('/js/thing/graph.js', ); + +HtmlHelper::registerCssAndScriptsFiles($cssAnsScriptFilesModule , $this->module->assetsUrl); + +$params = CO2::getThemeParams(); +$isAjax=null; + +if(!(Yii::app()->request->isAjaxRequest) ){ + $isAjax=false; + $layoutPath = 'webroot.themes.'.Yii::app()->theme->name.'.views.layouts.'; + //header + menu + $this->renderPartial($layoutPath.'header', + array( "layoutPath"=>$layoutPath , + "page" => "thing") ); + + +}else $isAjax=true; + +?> + +<!--link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/bootstrap3-editable/css/bootstrap-editable.css" rel="stylesheet" /> +<script type="text/javascript"> + $('head').append('<link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.1/jquery-editable/css/jquery-editable.css" rel="stylesheet" />'); + $.fn.poshytip={defaults:null}; +</script--> + +<?php +if(empty($nbDays) || !isset($nbDays) || $nbDays==0 ){$nbDays=7;} +else if ($nbDays>90) { $nbDays=90; } +if(empty($country) || !isset($country)){$country='RE';} +if(empty($postalCode) || !isset($postalCode)){$postalCode='0';} +else if (is_int($postalCode)){$postalCode=strval($postalCode);} + +//TODO remplacer par la function bylocality +$devicesMongoRes = Thing::getSCKDevicesByLocality($country,null,null,null,$postalCode); +//$devices=array(); +//print_r($devicesMongoRes); + +$sigDevicesForContextMap = array(); +$infoSensors=array(); + +$infoSensorsDeviceOk=false; + +//todo : utiliser les pois en objet sig, au lieu de construire des objets +foreach ($devicesMongoRes as $mdataDevice) { + $mdataDevice["typeSig"]='poi.'.Thing::SCK_TYPE; + //$devices[]=$mdataDevice; + $sigDevicesForContextMap[]= array('geo' => $mdataDevice['geo'], 'typeSig'=>'poi.'.Thing::SCK_TYPE, + 'name'=> "sck".$mdataDevice['deviceId'], '_id'=>$mdataDevice['_id'], 'type'=>Thing::SCK_TYPE, + 'address'=>$mdataDevice['address']); + + if(!$infoSensorsDeviceOk){ + $sensors=$mdataDevice['sensors']; + if(count($sensors)>=9){ + foreach ($sensors as $sensor) { + $infoSensors['sensor'.$sensor['id']] = array('id'=>$sensor['id'],'name' => $sensor['name'], + 'description'=>$sensor['description'],'unit'=>$sensor['unit']); + } + $infoSensors['timestamp']=$mdataDevice['timestamp']; + $infoSensors['kit']=$mdataDevice['kit']; + $infoSensorsDeviceOk=true; + } + } +} + +/* +if( Yii::app()->request->isAjaxRequest ){ + echo "<br/>"."Ajax"; +}*/ + +?> + +<style type="text/css"> +/*#graphs{ +overflow: scroll; + +}*/ +/*container*/ +.graphs{ + padding: 10px; + margin : 10px; + width: 100% ; + height: 100% ; +} +.svggraph{ + width: 100% ; + height: 100% ; + background-color: #fdfefd; + /*font-family: ;*/ + +} +#legend { + overflow: auto; + height: 80px; + width: 200px; + z-index: 1; +} + +#legend-graph { + color : black; + padding: 20px; + margin: 20px +} +#header-graph{ + +} + +.grid .tick { + stroke: lightgrey; + opacity: 0.7; +} +.grid path { + stroke-width: 0; +} + +#graph-container { + background-color: #fefefe; + +} +<?php if(!$isAjax ){ ?> +#graph-container{ + margin-top: 60px; + padding-top: 60px; +} +<?php }?> +</style> + +<div class="col-md-12 col-sm-12 col-xs-12 container" id="graph-container"> + <section class="header col-sm-12 col-xs-12 no-padding no-margin" id="header-graph"> + <form class="form-inline col-sm-12 col-xs-12"> + <div class="center form-group col-sm-12 col-xs-12"> + <div class="btn-toolbar col-sm-12 col-xs-12 no-padding no-margin" role="toolbar" aria-label="choixgraph" id="btngraphs" name="btngraphs"> + <span class="btn-group no-padding no-margin col-sm-12" role="group" aria-label="choixmesuressensors"> + <button type="button" class="btn btn-default btnchoixgraph " id="btnTempAndHum" title="Température et humidité" value="1"> + <i class="fa fa-thermometer-half"></i> <span class="hidden-sm hidden-xs">Température | humidité</span> </button> + <button type="button" class="btn btn-default btnchoixgraph" title="Énergies : Batterie et PV" value="2"> + <i class="fa fa-battery-full" ></i> <span class="hidden-sm hidden-xs">Énergies</span> </button> + <button type="button" class="btn btn-default btnchoixgraph" title="Luminosité" value="3"> + <i class="fa fa-sun-o" ></i> <span class="hidden-sm hidden-xs">Luminosité</span> </button> + <button type="button" class="btn btn-default btnchoixgraph" title="Gaz : CO et NO2" value="4"> + <i class="fa fa-cloud"> </i> <span class="hidden-sm hidden-xs">CO | NO2 </span> </button> + <button type="button" class="btn btn-default btnchoixgraph" title="Bruit" value="5"> + <i class="fa fa-volume-up" ></i> <span class="hidden-sm hidden-xs">Bruit | nets</span> </button> + <button type="button" class="btn btn-default btnchoixgraph" title="Tous les graphes" value="6"> + <i class="fa fa-check-square"></i> <span class="hidden-sm hidden-xs" >Tous</span> </button> + </span> + </div> + </div> + <div class="center btn-toolbar col-sm-12 form-group <?php echo 'hidden'; ?> " role="group" aria-label="choixtimeoffset" name="btnchoix"> + <button class="btn btn-default" id="btnchoixtimeoffset" type="button" title="timeoffset" value="0"> + <i class="fa fa-clock-o" id="ibtntimeoffset"></i><span class="hidden-sm hidden-xs"> Heure locale </span> </button> + <button class="btn btn-default" id="btntest" type="button" title="test" value="1"> + <i class="fa fa-clock-o" id="ibtntest"></i><span class="hidden-sm hidden-xs"> Test </span> </button> + </div> + + <div class="center btn-toolbar col-sm-12 form-group <?php if($isAjax){ echo 'hidden';} ?>" role="group" aria-label="choixsource" name="btnchoixsource"><span class="col-xs-12 col-md-3"> Source des données : </span> + <span class="btn-group no-padding no-margin col-xs-12 col-md-9" role="group"> + <button class="btn btn-default btngraphsource" id="btndcodb" type="button" title="timeoffset" value="0"> + <i class="fa fa-database" id="ibtndcodb"></i><span class="hidden-sm hidden-xs"> Communecter DB </span> </button> + <button class="btn btn-default btngraphsource" id="btndapisc" type="button" title="test" value="1"> + <i class="fa fa-cloud-download" id="ibtndapisc"></i><span class="hidden-sm hidden-xs"> Depuis API smartcitizen </span> </button> + <button class="btn btn-default btngraphsource" id="btnbothsource" type="button" title="test" value="2"> + <i class="fa fa-clone" id="ibtnbothsource"></i><span class="hidden-sm hidden-xs"> Comparaison des graphes </span> </button> + </span> + </div> + + <div class="form-group col-sm-12"> + + <!--<div class="no-all-day-range"> + <span class="input-icon"> + <input type="text" class="event-range-date form-control" name="eventRangeDate" placeholder="Range date"/> + <i class="fa fa-clock-o"></i> + </span> + </div> + <div class="all-day-range"> + <span class="input-icon"> + <input type="text" class="event-range-date form-control" name="ad_eventRangeDate" placeholder="Range date"/> + <i class="fa fa-calendar"></i> + </span> + </div>--> + <!-- TODO faire un selecteur de nombre de jours qui fait un get avec graph?nbDay=x --> + <label class="hide col-sm-12" id="period"> </label> + <label class="col-xs-12 col-sm-3 control-label" for="from">Période</label> + <span class="input-group col-xs-12 col-sm-8"> + <input class="form-group" type="text" id="datePickerFrom" name="datefrom"> + <input class="form-group" type="text" id="datePickerTo" name="dateto"> + </span> + </div> + </form> + </section> + <section class="body center col-sm-12 col-xs-12 no-padding" > + <div class="col-xs-12 no-padding" id="graphs"> + </div> + </section> + <section class="footer center col-sm-12 col-md-10 no-padding hidden" id="legend-graph"> + <div class="col-sm-12 col-md-10"> + <label class="col-xs-12 col-sm-3">Légende</label> + <div class="col-xs-12 col-sm-7" id="legend"></div> + </div> + </section> +</div> + +<!--?php $this->renderPartial($layoutPath.'footer', array("subdomain"=>"thing")); ?--> + +<script> + +//variable globale : +var tRollup = "24h"; +var coRollup = 1440; +var svgG; + +//var timeOffset=<?php //echo timezone_offset_get(DATE_ISO8601) ?> + +var nbDays=<?php echo $nbDays ?>; +//var nbDays=10; +if(nbDays>0 && nbDays<=2){ + tRollup = "10m"; //10 + coRollup = 10; +}else if (nbDays>2 && nbDays<=7 ){ + tRollup = "60m"; + coRollup = 60; +}else if (nbDays>7 && nbDays<=14) { + tRollup = "120m"; + coRollup = 120; +}else if(nbDays>14 && nbDays<= 30) { + tRollup = "12h"; + coRollup = 720; +} + +$("#period").text("Graphe sur "+nbDays+" jours, rollup : "+tRollup); +// +//mylog.log(); + +//svglegend={lwidth: 200, lheight: 100, }; + +//Variable pour d3 et svg +var multiGraphe = {}; +var strockeColorArray={}; + +var svgwidth = 500, svgheight = 285; //16:9 +var gmargin = {top: 20, right: 30, bottom: 30, left: 50}; +var gwidth = +svgwidth - gmargin.left - gmargin.right; +var gheight = +svgheight - gmargin.top - gmargin.bottom; + +var x = d3.scaleTime() + .rangeRound([0, gwidth]); + +var y = d3.scaleLinear() + .range([gheight, 0]); + +var line = d3.line() + .x(function(d) { return x(d.timestamps); }) + .y(function(d) { return y(d.values); }); + +var vXn = new Date("2017-03-20"); // 2017-05-03 +var vXm = new Date("2017-03-20"); +vXn.setDate((vXn.getDate()-nbDays)); +var dXmISO = vXm.toISOString(); +var dXnISO = vXn.toISOString(); +var timeOffset = vXn.getTimezoneOffset(); // RE : -240 +var vYn = 0; //min +var vYm = 1; + +//Variable SCK +//var listDevice = ["2531","4162","4151"];//,"4139","3151", "3188", "3422", "4122", "1693", "3208", "4164"];// +/* var devices = <?php //echo json_encode($devices,true) ?>; */ + +var devicemongoGraph=<?php echo json_encode($devicesMongoRes); ?>; +//mylog.log(devices); + +var listDevice = []; +var dCOdb = {}; +var dAPIsc = {}; +var graphReady= {dCOdb: false, dAPIsc : false}; +var min={} ; //null; +var max={} ; //null; + + +for (var device in devicemongoGraph ){ + lengthOflistDevice++; // pour avoir la taille rapidement + listDevice.push({deviceId : devicemongoGraph[device].deviceId, boardId : devicemongoGraph[device].boardId }); +}; +var lengthOflistDevice=listDevice.length; + +var deviceForBoardId={}; +//var listDevice = <?php //echo json_encode($deviceIds) ?>; +//mylog.log(listDevice); + +// TODO : recuperer les sensor id pour chaque device par lastest readings API SC cad les donné de la base COmmunecter POI +//var sckSensorIds = {bat : 17, hum : 13, temp : 12,no2 : 15, co: 16, noise : 7, panel : 18, light : 14 , nets : 21}; + +var dataSensors = { bat : { id : 17}, hum :{ id : 13}, temp :{ id : 12} ,no2 : { id :15}, + co:{ id : 16}, noise :{ id : 7}, panel :{ id : 18}, light :{ id : 14} , nets : { id :21} }; + +var infoSensors = <?php echo json_encode($infoSensors); ?>; +var compteurAjaxAPIsc=0; +var compteurDevices={}; +var lengthOfdataSensors=0; + +var boardIds = []; +var urlReqCODB = baseUrl+'/'+moduleId+"/thing/getsckdataincodb"; //?start="+dXnISO+"&end="+dXmISO+"&rollupMin="+coRollup; +var urlReqAPIsc="<?php echo Thing::URL_API_SC ?>/devices/";//+item.deviceId+"/readings"; +var contextDevicesMap = <?php echo json_encode($sigDevicesForContextMap,true);?>; +//var contextDevicesMap = <?php// echo json_encode( $devicesMongoRes ,true);?> + +jQuery(document).ready( function() { + + initKInterface({"affixTop":0}); + //initPageInterface(); + setTitle("<span id='main-title-menu'>Graphes</span>","line-chart","Graphes"); + $("#mainNav").addClass("affix"); + + +/* TODO remplacer par les poi pour sig ( mettre dans la page thing )*/ + + //chargement la carte + if(CoSigAllReadyLoad){ + Sig.showMapElements(Sig.map, contextDevicesMap); + }else{ + setTimeout(function(){ Sig.showMapElements(Sig.map, contextDevicesMap); }, 3000); + } + + //$("#legend-graph").hide(); + + for (var keySens in dataSensors ) { //forEach( function(item,index,array){ + lengthOfdataSensors++; + min[keySens]=null; + max[keySens]=null; + + var sensorId = dataSensors[keySens].id; // item[it]; + var nametitle= "graphe_"+sensorId; + var grapheTitle = d3.select("#graphs") + .append("figure").attr("id",nametitle) + .attr("class","col-xs-12 no-padding graphs"); + + $("#"+nametitle).hide(); + setSVGForSensor(sensorId, keySens); + } + + //$(".svggraph").hide(); + mylog.log('set SVG All Sensor done'); + + // var boardIdTest = "00:06:66:2a:02:a0"; + + listDevice.forEach( function(item) { + dAPIsc[item.deviceId]={temp : [], hum : [], bat: [], panel : [], no2 : [], panel : [], co : [], noise : [], nets : [], light : []}; + deviceForBoardId[item.boardId]=item.deviceId; + setStrokeColorAndLegendForDevice(item.deviceId); + if(item.boardId!="[FILTERED]"){ boardIds.push(item.boardId); } + }); + + mylog.log("listDevice : "); + mylog.log(listDevice); + + + $("#datePickerFrom").datepicker({ gotoCurrent: true, + maxDate: -1, dateFormat: "yy-mm-dd", + onSelect: function(date){ vXn.setDate(date); graphReady.dCOdb=false; graphReady.dAPIsc=false; } }); + $("#datePickerTo").datepicker({ gotoCurrent: true, + maxDate: 0, dateFormat: "yy-mm-dd", + onSelect: function(date){ vXm.setDate(date); graphReady.dCOdb=false; graphReady.dAPIsc=false; } }); + $("#datePickerFrom").datepicker("option", "dateFormat", "yy-mm-dd"); + $("#datePickerTo").datepicker("option", "dateFormat", "yy-mm-dd"); + $("#datePickerFrom").datepicker("setDate", vXn); + $("#datePickerTo").datepicker("setDate", vXm); + + + + $(".btngraphsource").click( function(){ + var value = $(this).val(); + $(".btngraphsource").removeClass("active"); + $(this).addClass("active"); + mylog.log(" value btn :"+value); + //$.datepicker.parseDate( "yy-mm-dd", ); + + showHideChart( value); + } + ); + + $(".btnchoixgraph").click(function(){ + var value = $(this).val(); + $(".btnchoixgraph").removeClass("active"); + $(this).addClass("active"); + //mylog.log(value); + + hideAllGraph(); + var list=[]; + switch(value) { + case "1": //temp et hum + list.push(12,13); + break; + case "2": //energie : batt et solarPV + list.push(17,18); + break; + case "3": //lum + list.push(14); + break; + case "4": //co no2 + list.push(15,16); + break; + case "5": //bruit : noise et nets + list.push(7,21); + break; + case "6": + showAllGraph(); + break; + //default: + // list.push(12,13); + // break; + } + for(var s=0;s<list.length; s++){ + var figGraph = "graphe_"+list[s]; + showGraph(figGraph); + } + }); + + +}); //fin jQuery ( document) + + +function initPageInterface(){ + + $("#second-search-bar").addClass("input-global-search"); + + $("#main-btn-start-search, .menu-btn-start-search").click(function(){ + startGlobalSearch(0, indexStepGS); + }); + + $("#second-search-bar").keyup(function(e){ + $("#input-search-map").val($("#second-search-bar").val()); + if(e.keyCode == 13){ + startGlobalSearch(0, indexStepGS); + } + }); + + $("#input-search-map").keyup(function(e){ + $("#second-search-bar").val($("#input-search-map").val()); + if(e.keyCode == 13){ + startGlobalSearch(0, indexStepGS); + } + }); + + $("#menu-map-btn-start-search").click(function(){ + startGlobalSearch(0, indexStepGS); + }); + + $(".social-main-container").mouseenter(function(){ + $(".dropdown-result-global-search").hide(); + }); +} + + +function setGraphFromAPIsmartcitizen() { + //$.blockUI({ message : '<span class="homestead"><i class="fa fa-spinner fa-circle-o-noch"></i> Chargement des données en cours ...</span>' }); + // fait un graphe par sensor et trace tous les devices sur le même graphe sensor + mylog.log("--- processGraphAPI ---"); + + for(var keySens in dataSensors){ + var sensorId = dataSensors[keySens].id; + compteurDevices[keySens]=0; + + listDevice.forEach( function (item) { + ///?sensor_id="+sensorId+"&"+tRollup+"&from="+dXnISO+"&to="+dXmISO; + //exemple api GET https://api.smartcitizen.me/v0/devices/1616/readings?sensor_id=7&rollup=4h&from=2015-07-28&to=2015-07-30 + var deviceId = item.deviceId; + var urlReqSC=urlReqAPIsc+deviceId+"/readings"; + + $.ajax({ + type: 'GET', + url: urlReqSC, + dataType: "json", + data : {sensor_id : sensorId, rollup: tRollup, from: dXnISO, to: dXmISO}, + crossDomain: true, + context : { keySens: keySens, deviceId: deviceId , lengthOflistDevice : lengthOflistDevice }, + success: function (data) { + + var ks = $(this)[0].keySens; + var dvice=$(this)[0].deviceId; + mylog.log(data); + + if (data.readings.length>=1){ + fillArrayWithObjectTimestampsAndValues(data.readings, dvice, ks); + } + }, + error: function (dErr) { + mylog.log("Error : ajax not success"); + //mylog.log(dErr); + mylog.log( "error sensor : "+$(this)[0].keySens+" device :"+$(this)[0].deviceId); + }, + complete : function( ) { + mylog.log("Complete ajax "); + var ks = $(this)[0].keySens; + var dvice=$(this)[0].deviceId; + if(++compteurDevices[ks] >= (lengthOflistDevice)){ + mylog.log( "--compteurDevices - "+ks+" : "+dvice); + grapheOneSensor(ks, "dAPIsc",false); + } + } + }); + }); //forEach + } // for +} + +function setGraphFromCoDB () { + console.time("ajaxRequestToCODB"); + //$.blockUI({ message : '<span class="homestead"><i class="fa fa-spinner fa-circle-o-noch"></i> Chargement des données en cours ...</span>' }); + + $.ajax({ + type: 'GET', + url: urlReqCODB, + dataType: "json", + data: { start : dXnISO, end : dXmISO, rollupMin: coRollup, + listBoardIds : JSON.stringify(boardIds) }, + context : { listDevice: listDevice}, + success: function (dCO) { + mylog.log(" -- ajax success-- " ); + if(notNull(dCO) ){ + mylog.log("--deviceForBoardId in ajax- "); + mylog.log(deviceForBoardId); + + for( var bId in dCO){ + mylog.log("---- boardIds ---- "+ bId); + if(dCO[bId].length>0 ){ + + var deviceId = deviceForBoardId[bId]; + dataSensorAdaptorTimestampsAndValues(dCO[bId],deviceId ); + } + } + } + }, + error: function (data) { mylog.log("Error : ajax not success -- "); + mylog.log(data); + } + + }).done(function() { + mylog.log(" -- ajax Done-- " ); + console.timeEnd("ajaxRequestToCODB"); + + for(var ks in multiGraphe ){ + grapheOneSensor(ks,"dCOdb",false); + } + }); +} + + + + + + + +mylog.log("------------ jusqu'ici tous va bien pour graph !! ----------------"); +</script> \ No newline at end of file diff --git a/views/thing/manage.php b/views/thing/manage.php new file mode 100644 index 00000000..c78a9cda --- /dev/null +++ b/views/thing/manage.php @@ -0,0 +1,205 @@ +<?php + $cs = Yii::app()->getClientScript(); + + // $cssAnsScriptFilesModule = array( + // '/plugins/d3/d3.v3.min.js', + // ); + // HtmlHelper::registerCssAndScriptsFiles($cssAnsScriptFilesModule, Yii::app()->request->baseUrl); + $layoutPath = 'webroot.themes.'.Yii::app()->theme->name.'.views.layouts.'; + //header + menu + $this->renderPartial($layoutPath.'header', + array( "layoutPath"=>$layoutPath , + "page" => "thing") ); + + + if(empty($country)){$country='RE';} +?> + +<?php + $devicesMongoRes = Thing::getSCKDevicesByLocality($country); + + $isAjaxR=(Yii::app()->request->isAjaxRequest); + +?> + +<style> + +<?php if(!$isAjaxR ){ ?> +#managesck{ + margin-top: 40px; + padding-top: 40px; +} +<?php }?> + + +</style> + +<?php if(!$isAjaxR ){ ?> + <?php $this->renderPartial($layoutPath.'footer', array("subdomain"=>"thing")); ?> +<?php } ?> + + + +<div class="col-xs-12 container" id="managesck"> + <div class="col-xs-12 <?php if($isAjaxR){echo 'hidden';}?> sck-maj" id="sck-maj-principal"> + <h4>Mettre à jour les métadatas de la base communecter</h4> + <p>Si vous avez un compte <a href="https://smartcitizen.me" target='_blank'>smartcitizen.me</a> vous pourrez mettre à jours les adresse mac de vos kit qui sont communectés (double push). Utiliser le token smarticitizen, pour plus d'information sur l'authentification et le token voir la page <a href="http://developer.smartcitizen.me/#authentication" target='_blank'>developper.smartcitizen.me</a>. + </p> + + <form name="formwithauth" class="form-inline col-sm-12" id="formupdatewithauth" action="javascript:updateSCKMetadata()"> + <span class='form-group col-sm-12' role='group'> + <label class="col-xs-12 col-sm-3 col-md-3" for="tokenSC"> Token d'accès SC </label> + <input class="col-xs-12 col-sm-4 col-md-4" type="text" id="tokenSC" name="tokenSC" value=""> + <button class="btn btn-default col-sm-4 col-md-3 " id="btn-updatesck" type="submit" > MAJ métadatas </button> + </span> + </form> + <div class="hidden col-xs-12" id="resultat-update"></div> + </div> + + <div class="col-xs-12 <?php if($isAjaxR){echo 'hidden';}?> sck-maj" id="sck-maj-secondaire"> + <h4>Ajouter les adresses mac des Smart-Citizen-kit</h4> + <p> </p> + <form name="formboardid" class="form-inline col-sm-12" id="formboardid" action="javascript:updateSCKBoardId()"> + <?php + foreach ($devicesMongoRes as $mdataDevice) { + if($mdataDevice["boardId"]=="[FILTERED]"){ + //$devices[]=$mdataDevice; + ?> + <div class='form-group col-sm-12' role='group'> + <span id='<?php echo $mdataDevice['_id'] ?>'> + <label class="col-sm-6 col-xs-12">Le kit + <a href='https://smartcitizen.me/kits/<?php echo $mdataDevice["deviceId"];?>' target='_blank'> <?php echo $mdataDevice["name"];?> (deviceId : <?php echo $mdataDevice["deviceId"];?>) + </a> + </label> + <span class="col-sm-6 col-xs-12" id=" "> + <input type='text' class="deviceids form-control" name='mac-sck-<?php echo $mdataDevice['deviceId']?>' id='mac-sck-<?php echo $mdataDevice['deviceId']?>' value=""> + <input class='idMdataDevice hide' name='idmeta<?php echo $mdataDevice['deviceId']?>' value='<?php echo $mdataDevice['_id'] ?>' readonly> + <i class="fa fa-check hidden "> </i> + </span> + </span> + </div> + <?php } + }?> + <input id="btnudpateboardid" type="submit" value="Mettre à jour"> + </form> + </div> +</div> + +<?php if(!$isAjaxR ){ + $this->renderPartial($layoutPath.'footer', array("subdomain"=>"thing")); +} ?> + +<script> + +patternMacId = /([0-9a-f]{2}[:-]){5}([0-9a-f]{2})/; + +function updateSCKBoardId(){ + + sckDeviceIdBoardId=[]; + $.each(devicesMongoRes, function(id,mdata){ + deviceId= mdata.deviceId; + boardId = $("#mac-sck-"+deviceId).val(); + //mylog.log("board : "+boardId); + + if(patternMacId.test(boardId)){ + $("#mac-sck-"+deviceId).addClass("has-success"); + sckDeviceIdBoardId.push({deviceId,boardId}); + + } /*else if (boardId==""){ + mylog.log("warning"); + $("#mac-sck-"+deviceId).addClass("has-warning"); + }else{ + mylog.log("error"); + $("#mac-sck-"+deviceId).addClass("has-error"); + } */ + } ); + + //mylog.log(sckDeviceIdBoardId); + //JSON.stringify(sckDeviceIdBoardId); + urlrequest = baseUrl+'/'+moduleId+'/thing/updatesckdevices'; + $.ajax({ + type: 'POST', + url: urlrequest, + data: {listbd : sckDeviceIdBoardId}, + dataType: "json", + crossDomain: true, + success: function(data){ + + mylog.log("success"); + }, + error : function (data) {mylog.log("Error : ajax not success"); } + }).done(function() { + //mylog.log('post done'); + }); + + +} + +function updateSCKMetadata(){ + //$.blockUI({ message: "<div> update en cours</div>" }); + mylog.log("updateSCKMetadata *** "); + atSC = $("#tokenSC").val(); + if(atSC==""){ + urlrequest = baseUrl+'/'+moduleId+'/thing/updatesckdevices'; + }else{ + urlrequest = baseUrl+'/'+moduleId+'/thing/updatesckdevices?atSC='+atSC; + } + + $("#btn-updatesck").removeClass("btn-default"); + $("#btn-updatesck").addClass("btn-warning"); + + mylog.log('urlrequest : ' +urlrequest); + + $.ajax({ + type: 'GET', + url: urlrequest, + dataType: "json", + crossDomain: true, + success: function (data) { + $("#btn-updatesck").removeClass("btn-warning"); + $("#btn-updatesck").addClass("btn-success"); + }, + error : function (data) {mylog.log("Error : ajax not success"); } + }).done(function(data) { + textres=""; + if(notNull(data.devicesmetadata.elementsAlreadyUpdate) && data.devicesmetadata.elementsAlreadyUpdate>0 ){ + textres+='<p> Nombres d\'élements déjà MAJ : '+ data.devicesmetadata.elementsAlreadyUpdate+ '</p>'; + } + if(notNull(data.devicesmetadata.elementsUpdated) && data.devicesmetadata.elementsUpdated>0){ + textres+= '<p> Nombres d\'élements mis à jour : '+ data.devicesmetadata.elementsUpdated+ '</p>'; + } + if(notNull(data.devicesmetadata.elementsBad) && data.devicesmetadata.elementsBad>0 ){ + textres+= '<p> Nombres d\'élements non mis à jour : '+ data.devicesmetadata.elementsBad+ '</p>'; + } + if( notNull(data.APIMetadata) && data.APIMetadata.length>0){ + data.APIMetadata.forEach( + function(item,index){ + mylog.log("méta API maj : "); + textres+= '<p> Metadata API mis à jour : '+item+' .</p>' ; + }); + } + + $("#resultat-update").html(textres); + + $("#resultat-update").removeClass("hidden"); + $("#btn-updatesck").addClass("btn-success"); + }); +} + +jQuery(document).ready(function() { + initKInterface({"affixTop":0}); + + devicesMongoRes = <?php echo json_encode($devicesMongoRes); ?> ; + + //mylog.log(devicesMongoRes); + + /* + $("#btn-updatesck").off().on("click",function(){ + mylog.log("*** #btn-updatesck * "); + updateSCKMetadata(); }); + */ + + setTitle("Gestion SCK","fa-database"); +}); + +</script> \ No newline at end of file diff --git a/views/thing/scklastestreadings.php b/views/thing/scklastestreadings.php new file mode 100644 index 00000000..24777633 --- /dev/null +++ b/views/thing/scklastestreadings.php @@ -0,0 +1,302 @@ +<?php +$cssAnsScriptFilesModule = array( + + ); +HtmlHelper::registerCssAndScriptsFiles($cssAnsScriptFilesModule, Yii::app()->request->baseUrl); +//$cs = Yii::app()->getClientScript(); + +$params = CO2::getThemeParams(); + +$layoutPath = 'webroot.themes.'.Yii::app()->theme->name.'.views.layouts.'; + +$isAjaxR=(Yii::app()->request->isAjaxRequest); + +if(!$isAjaxR){ + +//header + menu + $this->renderPartial($layoutPath.'header', + array( "layoutPath"=>$layoutPath , + "page" => "thing") ); +} + +$communexion = CO2::getCommunexionCookies(); + +$sckInfo=array('boardIdFiltered'=>0,'sensorsCheck'=>false, 'sckSensors'=>false, 'notInCODB'=>array()); + +$devices = array(); +$lastesRecordsCODB=array(); +$sensors= array(); + +$country=null; $regionName=null; $depName=null; $cityName = null; + +if($communexion["state"] == false){ + $country='RE'; +}else { + $depName = (!empty($communexion['values']['depName'])) ? $communexion['values']['depName']: null; + $cityName = (!empty($communexion['values']['cityName'])) ? $communexion['values']['cityName']: null; + $regionName=(!empty($communexion['values']['regionName']))? $communexion['values']['regionName']: null; +} + +$devices = Thing::getSCKDevicesByLocality($country, $regionName, $depName, $cityName, null, null); + +// Le type doit etre unique pour getSCKDeviceMdata findOne prend la première ocurrence : +$sckMdataSensors = (array) (Thing::getSCKDeviceMdata(Thing::COLLECTION_METADATA,array("type"=>"sckSensors"))); + +$sckSensors=$sckMdataSensors['sckSensors']; +$deviceByLocality = array(); + +foreach ($devices as $id => $device) { + + if($device['boardId']=='[FILTERED]'){ + $sckInfo['boardIdFiltered']++; + }else{ + //TODO ou Amelioration : Envoyé un message resultat pour signaler les boardId (device) qui ne sont pas dans la base communecter (pas double push) + /* TODO : mettre des description de sensor pour différente version de kit 1.1 1.2 ...etc... + * Utiliser device['kit'] pour la version sckSensors et measurement + */ + if(isset($device['sensors']) && !empty($device['sensors']) && $sckInfo['sensorsCheck']==false){ + $sckInfo['sensorsCheck']=true; + $sensors = $device['sensors']; + + foreach ($sensors as $key => $sensor) { + foreach ($sckSensors as $sckSensor) { + //var_dump($sckSensor); + if($sckSensor['id'] == $sensor['id']){ + if(!empty($sckSensor['measurement'])) + $sensors[$key]['measurement']=$sckSensor['measurement']; + break; + } + } + } + } + + if(isset($device['address'])){ + + $newDevice= array("deviceId"=>$device['deviceId'],"name"=>$device['name'],"boardId"=>$device['boardId'], + "sensors"=>array(),"timestamp"=>$device['timestamp'],"geo"=>$device['geo'],"latestCODB"=>array() ); // TODO ? : ajouter kit ? + $newSensor=array(); + + $lastesRecordsCODB[$device['deviceId']] = Thing::getLastestRecordsInDB($device['boardId']); + if(empty($lastesRecordsCODB[$device['deviceId']])){ + $sckInfo['notInCODB'][$device['deviceId']]=true; + //unset($lastesRecordsCODB[$device['deviceId']]); + //unset($devices[$id]); + }else{ + $newDevice['latestCODB']=$lastesRecordsCODB[$device['deviceId']]; + } + //Voir l'utilité : + foreach ($device['sensors'] as $key => $nsensor) { + $newSensor[$nsensor['id']] = $device['sensors'][$key]; + unset($newSensor[$nsensor['id']]['id'],$newSensor[$nsensor['id']]['ancestry'],$newSensor[$nsensor['id']]['created_at']); + unset($newSensor[$nsensor['id']]['updated_at'], $newSensor[$nsensor['id']]['uuid']); + } + + $newDevice['sensors']=$newSensor; + // + if(isset($device['address']['addressLocality'])){ + $deviceByLocality[$device['address']['addressLocality']][$id]=$newDevice; + }else if(isset($device['address']['postalCode'])){ + $deviceByLocality[$device['address']['postalCode']][$id]=$newDevice; + } + } + } +} + +?> + +<style type="text/css"> + +.row-codb{ + background-color: #ddfeee; + +} + +</style> + +<div class="col-sm-12 col-md-12 container"> + +<?php +if(!empty($sensors)){ + foreach ($sensors as $sensor) { + $itemSckSensor=array(); +// TODO : faire une div avec les boutons selection pour la page standalone +// remplir une variable avec tous les boutons et l'utilisé en js pour l'afficher si standalone class des bouton mm que ce dans thing +?> + <div class="col-sm-12 no-padding no-margin reading hidden" id="sensor-<?php echo $sensor['id']?>"> + <div class="row col-sm-12"> + <h4 class="text-blue col-md-4 col-sm-4 col-xs-12" id='h-title-<?php echo $sensor['id']?>'> + <i class='fa ' id='h-title-icon-<?php echo $sensor['id']?>' ></i> + <span class='' id='h-title-text-<?php echo $sensor['id']?>'> <?php echo $sensor['measurement']['name'] ?> </span> + </h4> + <div class="col-md-8 col-sm-8 hidden-xs" class="h-desc-<?php echo $sensor['id']?>"> + <?php echo $sensor['measurement']['description'] ?> + </div> + </div> + + <div class="row col-sm-12 no-padding no-margin"> + <h5 class="text-green no-padding no-margin"> + <span class="col-md-2 col-sm-2 col-xs-12">Ville</span> + <span class="col-md-4 col-sm-4 col-xs-12">Nom du SCK <span class="hidden-xs"> | Capteur</span></span> + <span class="col-md-4 col-sm-4 col-xs-12 text-center">Timestamp</span> + <span class="col-md-2 col-sm-2 col-xs-12 no-padding no-margin">Val<span class="hidden-xs no-padding no-margin">eur</span>(<?php echo $sensor['unit'] ?>)</span> + </h5> + </div> + + <?php + foreach ($deviceByLocality as $locality => $listdevices) { + ?> + + <div class="row col-sm-12 no-padding no-margin"> + + <h5 class="col-md-2 col-sm-2 col-xs-12 title-<?php echo $locality ?>"> <?php echo $locality ?> </h5> + + <div class="row col-md-10 col-sm-10 col-xs-12 no-padding no-margin " > + <?php + foreach ($listdevices as $ndevice) { + //$bcolor= + ?> + <div class="row col-sm-12 col-md-12 no-padding div-device" style=" "> + <div class="col-sm-5 col-md-5 no-padding no-margin"> + <h6 class="col-sm-12 col-md-12"><?php echo $ndevice['name'] ?> <span class="hidden-xs">| <?php echo $ndevice['sensors'][$sensor['id']]['name'] ?></span> + </h6> + </div> + <div class="col-sm-7 col-md-7 no-padding no-margin"> + + <div class="row col-md-12 col-sm-12 row-codb no-padding no-margin"> + <?php + $fromCOdb=(empty($ndevice['latestCODB']))? false : true; + $latestInfo=($fromCOdb)? "latestCODB" : "lastUpdatePOI" ; + ?> + + <div class="col-md-7 col-sm-7 no-padding no-margin text-center" title="<?php echo $latestInfo?>"> + <?php + if($fromCOdb){ + if(!empty($ndevice['latestCODB']['timestamp'])) + echo $ndevice['latestCODB']['timestamp']; + }else{ + if(!empty($ndevice['timestamp'])) + echo $ndevice['timestamp']; + } + ?> + </div> + + <div class="col-md-5 col-sm-5 no-padding no-margin text-center" title="<?php echo $latestInfo?>"> + <?php + if($fromCOdb){ + if(!empty($ndevice['latestCODB'][$sensor['measurement']['name']])) + echo round($ndevice['latestCODB'][$sensor['measurement']['name']],3); + }else{ + if (!empty($ndevice['sensors'][$sensor['id']]['value'])) + echo round($ndevice['sensors'][$sensor['id']]['value'],3) ; + } + ?> + </div> + </div> + + <div class="row col-sm-12 col-md-12 row-api no-padding no-margin hidden" id="row-api-sensor<?php echo $sensor['id']."-device".$ndevice['deviceId'] ?>" > + <div class="col-md-7 col-sm-7 no-padding no-margin text-center" id="api-timestamp-sensor<?php echo $sensor['id']."-device".$ndevice['deviceId'] ?>" title="obtenue par api.smartcitizen.me" > + + </div> + <div class="col-md-5 col-sm-5 no-padding no-margin text-center" id="api-value-sensor<?php echo $sensor['id']."-device".$ndevice['deviceId'] ?>" title="obtenue par api.smartcitizen.me" > + + </div> + + </div> + </div> + </div> + <?php + } //fin foreach listdevice + ?> + </div> + </div> + <?php + } // fin foreach devicebylocality + ?> + <hr class="col-md-12 col-sm-12 col-xs-12 no-padding "> + </div> + +<?php + } // fin foreach sensor +} // fin if +?> + +</div> + +<?php if(!$isAjaxR ){ +$this->renderPartial($layoutPath.'footer', array("subdomain"=>"thing")); +} ?> + +<script> +//en correspondance avec subcat dans le fichier thing.json +var subcatscktoshow = [{"Temperature et humidité" : ["temp", "hum" ] }, {"Gaz":["co", "no2"]}, {"Lumière":["lum"]} , {"Bruit":["noise"]} , {"Nets" :["nets"]}, {"Énergie":["bat","pv"]}, {"Tous": ["all"]}]; + +var deviceByLocality=<?php echo json_encode($deviceByLocality) ; ?>; + +var urlReq="<?php echo Thing::URL_API_SC ?>/devices/"; + +var devicelastreads = <?php echo json_encode($devices); ?>; + +jQuery(document).ready(function() { + initKInterface({"affixTop":0}); + + mylog.log(deviceByLocality); + for(var v in deviceByLocality){ + // for chaque ville (si plusieur ville) + for(var id in deviceByLocality[v]){ + mylog.log(deviceByLocality[v][id].deviceId); + getDeviceReadings(deviceByLocality[v][id].deviceId); + } + } + setTitle("Dernières mesures","cog"); +}); + + +function getDeviceReadings(deviceId) { + if(notNull(deviceId)){ + $.ajax({ + type: 'GET', + url: urlReq+deviceId, + dataType: "json", + crossDomain: true, + success: function (data) { + //mylog.log(data); //resultat de la requete à l'api + if(data.id==deviceId){ + sensors = data.data.sensors; + thetimestamp = data.data.recorded_at; + sensors.forEach(function(item, index){ + sensorId = item.id; + //value = Math.round(item.value*1000)/1000; + value = +(Math.round(item.value + "e+3") + "e-3"); + $("#api-timestamp-sensor"+sensorId+"-device"+deviceId).text(thetimestamp); + $("#api-value-sensor"+sensorId+"-device"+deviceId).text(value); + $("#row-api-sensor"+sensorId+"-device"+deviceId).removeClass("hidden"); + }); + } + }, + error: function (data) { + mylog.log("Error : ajax not success"); + } + }).done(function() { mylog.log("ajax api.smartcitizen.me done"); }); + } +} + +/* Première version en tableau (tous étaient créé coté client) + var sensors = <?php //echo json_encode($sensors); ?>; + var tbody = document.getElementById("tbody"); + sensors.forEach( function(item){ + var ligne=[item.id,item.name,item.value,item.value,item.unit,item.description]; + var tr = document.createElement("tr"); + tbody.appendChild(tr); + for (var i=0;i<ligne.length;i++){ + var td = document.createElement("td"); + td.innerHTML=ligne[i].toString(); + if(i==ligne.length-1){ + td.setAttribute("class","hide description"); + //td.setAttribute("id","" ) + } + tr.appendChild(td); + } + tbody.appendChild(tr); + }); */ + +</script>