Sida 3 av 4
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 04 mar 2014, 23:12
av Plutonium
Det är ingen fara Flyvert, familjen är det viktigaste.. Jag finns kvar här ett bra tag till
Wow, låter som ett gediget projekt med hemmabion

Förstår att du har fullt upp.
Jag röstar på: Das Boot

Re: Behöver lite hjälp att komma igång med "flot"
Postat: 23 sep 2016, 18:42
av P-G
Jag försöker att skapa grafer i Flot men lyckas inte. Jag får en tom graf precis som flyvert, men förstår inte vad som skall ändras.
Select plockar ut timmar och kwh
Kod: Markera allt
<html>
<head>
<title>Flot Examples</title>
<script src="../jquery.js"></script>
<script src="../jquery.flot.js"></script>
<script src="../jquery.flot.time.js"></script>
</head>
<body>
<h1>Flot Examples</h1>
<div id="placeholder" style="width:600px;height:300px;"></div>
<?php
$db = mysql_connect("localhost", "user", "password");
mysql_select_db("temperaturen",$db);
$query = "SELECT energy.timegroup as Hour, round( sum( energy.countdiff ) / 1000, 1) as kWhDiff
FROM( SELECT i.counter_c - c.counter_c as countdiff, c.counter_c as startcounter, date_format( c.timestamp,'%Y-%m-%d %T' ) as timegroup
FROM elmatare c join (select * FROM elmatare) i on c.index=i.index-1 and c.timestamp between timestampadd( hour, -24, Now() ) and Now()) energy,
(SELECT min(s.counter_c) as countstart FROM elmatare s join (select * FROM elmatare) t on s.index=t.index and s.timestamp between timestampadd(hour,-24, Now()) and Now()) input group by energy.timegroup";
$result = mysql_query($query,$db);
while($row = mysql_fetch_array($result))
{
// $arr[] = array($row->Hour,$row->kWhDiff);
$arr[] = array($row["Hour"],$row["kWhDiff"]);
}
?>
<script type="text/javascript">
$(function () {
var dataset1 = <?php echo json_encode($arr); ?>;
$.plot($("#placeholder"), [ dataset1 ] );
});
</script>
</body>
</html>
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 24 sep 2016, 10:38
av flyvert
Den avgörande skillnaden är att du inte valt att köra med AJAX som jag gör i min lösning. Med AJAX drar webbläsaren in Flot och postar en HTTP GET tillbaka till webbservern där ett PHP skript gräver upp datat, gör om till JSON och skickar tillbaka till den väntande webbsidan. När datat kommer uppdateras Flot. Detta görs asynkront och öppnar upp för om du i framtiden vill ha en kontinuerligt uppdaterande kurva utan att måsta ladda om webbsidan hela tiden.
Har du studerat AJAX exemplen på
http://www.flotcharts.org/flot/examples?
Jag läser tabellen med PHP, konverterar till JSON o skickar med AJAX för att slutligen ta emot arrayerna i JavaScriptet som anropar Flot.
Testa att det kommer
rätt formaterad data med tex curl eller wget, en måsvinge, hakparentes eller dubbelfnutt (") för mycket eller för litet kan välta hela lasset!
Har för mig att man även kan slänga in "msgbox" i javascriptet för att debugga innehållet i variabler o arrayer.
http://www.flotcharts.org/flot/examples ... rowth.json
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 25 sep 2016, 12:10
av P-G
Nu har jag fått in trenden i grafen.
Det som blir fel nu är datumen och det har jag läst i detta inlägg att flyvert också fått men visar inte hur han har gjort.
Min SQL fråga har jag tagit från min Msure, är det någon som har en som fungerar med Flot?
Jag vet inte hur man multiplicerar med 1000 i min SQL-fråga för timestamp skall bli rätt.
Kod: Markera allt
SELECT energy.timegroup as 'Hour', round( sum( energy.countdiff ) / 1000, 1) as 'kWhDiff'
FROM(SELECT i.counter_c - c.counter_c as 'countdiff', c.counter_c as 'startcounter', date_format( c.timestamp,'%H:00:00') as 'timegroup'
FROM elmatare c join (select * FROM elmatare) i on c.index=i.index-1 and c.timestamp between timestampadd( hour, -24, Now() ) and Now()) energy,
(SELECT min(s.counter_c) as 'countstart'
FROM elmatare s join (select * FROM elmatare) t on s.index=t.index and s.timestamp between timestampadd(hour,-24, Now()) and Now()) input group by energy.timegroup
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 26 sep 2016, 23:54
av flyvert
Bara å multiplicera med 1000.
Från min kod tidigare i denna tråd:
$framledning[] = array((strtotime($row->time))*1000, $row->data);
Har inte haft tid att kolla i min nuvarande kod, men man borde läsa ut rätt format på direkten för att slippa konverteringar mellan sträng o decimalt.
Istället för att läsa tid som sträng från databasen, konvertera till UNIX timestamp o multiplicera med 1000 som ovan klipp ger sken av.
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 27 sep 2016, 00:00
av flyvert
Saxat från mitt aktuella "grävarskript" (skrivet i PHP) som Flot anropar via AJAX.
Multipliceringen markerad i blått.
$query = "SELECT UNIX_TIMESTAMP(time)*1000 \"time\", value from data where sensorid=$sensorid and property=$property and aggregate=$aggregate and period=$period and $ts order by time";
$result = @mysql_query ($query);
$arr = array();
while($row = mysql_fetch_object($result))
{
$arr[] = array($row->time*1,$row->value*1);
}
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 27 sep 2016, 20:37
av P-G
Har skrivit in enligt ditt förslag
resultatet blir detsamma
Kod: Markera allt
$query = "SELECT UNIX_TIMESTAMP(timestamp)*1000 \"timestamp\", temperature FROM ute WHERE timestamp > NOW() - INTERVAL 1 DAY ORDER by timestamp";
$result = @mysql_query ($query);
$utetemp = array();
while($row = mysql_fetch_object($result))
$arr[] = array($row->timestamp, $row->temperature);
mysql_close();
?>
<script type="text/javascript">
$(function () {
var dataset1 = <?php echo json_encode($arr); ?>;
$.plot($("#placeholder"), [ dataset1 ] );
});
</script>
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 28 sep 2016, 19:47
av flyvert
Hej PG
Ser att du funnit bland de allra första försöken med Flot som jag la ut här på forumet först i denna tråd. Hoppa ned till inlägget jag gjorde den 5:e september så får du bättre vägledning:
linux/behover-lite-hjalp-att-komma-igan ... tml#p20740
Och söker du på "Customizing the axis" på denna mycket matnyttiga URL får du mer hjälp.
https://github.com/flot/flot/blob/master/API.md
Som t.ex. att du måste ändra mode till "time"
var options = {
xaxis: { mode: "time", timezone: "browser" },
Här har du en dump av aktuell kod som jag kör, den innehåller lite mer av prylarna från Flot, t.ex stöd för zoom samt crosshair för att avläsa Y-värden. Jag har även lagt till knappar för att byta scope (har ännu inte fixat panorering) - varje gång jag trycker på en knapp tömmer jag data och skickar en ny läsförfrågan till mitt "grävarskript" via Ajax. När skriptet returnerar så ritas trenden om med det nya datat.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Signaler från fjärrvämeväxlare</title>
<link href="givare.css" rel="stylesheet" type="text/css">
<!--[if lte IE 8]><script language="javascript" type="text/javascript" src="1wire/flot/excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="1wire/flot/jquery.js"></script>
<script language="javascript" type="text/javascript" src="1wire/flot/jquery.flot.js"></script>
<script language="javascript" type="text/javascript" src="1wire/flot/jquery.flot.time.js"></script>
<script language="javascript" type="text/javascript" src="1wire/flot/jquery.flot.navigate.js"></script>
<script language="javascript" type="text/javascript" src="1wire/flot/jquery.flot.resize.js"></script>
<script language="javascript" type="text/javascript" src="1wire/flot/jquery.flot.crosshair.js"></script>
<style type="text/css">
html, body {
height: 97%; /* make the percentage height on placeholder work */
}
.message {
padding-left: 50px;
font-size: smaller;
}
</style>
</head>
<body>
<button class="moveScopeLeft"><<</button>
<button class="setScope10y">10 years</button>
<button class="setScope1y">1 year</button>
<button class="setScope6mo">6 months</button>
<button class="setScope3mo">3 months</button>
<button class="setScope1mo">1 month</button>
<button class="setScope1w">1 week</button>
<button class="setScope1d">1 day</button>
<button class="setScope12h">12 hours</button>
<button class="setScope6h">6 hours</button>
<button class="setScope1h">1 hour</button>
<button class="moveScopeRight">>></button>
<div id="placeholder" style="width:100%;height:100%;"></div>
<script type="text/javascript">
$(function() {
function degreeFormatter(v, axis) { return v.toFixed(axis.tickDecimals) +" °C"; }
function percentFormatter(v, axis) { return v.toFixed(axis.tickDecimals) +" %"; }
function hPaFormatter(v, axis) { return v.toFixed(axis.tickDecimals) +" hPa"; }
function luxFormatter(v, axis) { return v.toFixed(axis.tickDecimals) +" lux"; }
function wattFormatter(v, axis) { return v.toFixed(axis.tickDecimals) +" watt"; }
var options = {
xaxis: { mode: "time", timezone: "browser" },
yaxis: { tickFormatter: degreeFormatter },
zoom: { interactive: true },
legend: { position: "nw" },
crosshair: { mode: "x" },
grid: { hoverable: true, autoHighLight: true },
pan: { interactive: true } };
var data = [];
var plot = "";
var legends = "";
function onDataReceived(series) {
// window.alert("Data!");
data.push(series);
plot = $.plot("#placeholder", data, options);
legends = $("#placeholder .legendLabel");
}
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=2&scope=1d&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=2&scope=1d&color=1", type: "GET", dataType: "json", success: onDataReceived });
$("button.setScope").click(function () {
var button = $(this);
// Find the URL in the link right next to us, then fetch the data
var dataurl = button.siblings("a").attr("href");
window.alert(dataurl);
});
$("button.setScope1h").click(function () {
data = [];
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=1&period=1&scope=1h&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=1&period=1&scope=1h&color=1", type: "GET", dataType: "json", success: onDataReceived });
});
$("button.setScope6h").click(function () {
data = [];
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=1&period=1&scope=6h&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=1&period=1&scope=6h&color=1", type: "GET", dataType: "json", success: onDataReceived });
});
$("button.setScope12h").click(function () {
data = [];
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=1&period=1&scope=12h&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=1&period=1&scope=12h&color=1", type: "GET", dataType: "json", success: onDataReceived });
});
$("button.setScope1d").click(function () {
data = [];
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=2&scope=1d&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=2&scope=1d&color=1", type: "GET", dataType: "json", success: onDataReceived });
});
$("button.setScope1w").click(function () {
data = [];
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=2&scope=1w&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=2&scope=1w&color=1", type: "GET", dataType: "json", success: onDataReceived });
});
$("button.setScope1mo").click(function () {
data = [];
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=2&scope=1mo&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=2&scope=1mo&color=1", type: "GET", dataType: "json", success: onDataReceived });
});
$("button.setScope3mo").click(function () {
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=2&scope=3mo&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=2&scope=3mo&color=1", type: "GET", dataType: "json", success: onDataReceived });
data = [];
});
$("button.setScope6mo").click(function () {
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=3&scope=6mo&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=3&scope=6mo&color=1", type: "GET", dataType: "json", success: onDataReceived });
data = [];
});
$("button.setScope1y").click(function () {
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=3&scope=1y&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=3&scope=1y&color=1", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=3&period=4&scope=1y&color=1&type=points&nolabel=1", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=4&period=4&scope=1y&color=1&type=points&nolabel=1", type: "GET", dataType: "json", success: onDataReceived });
data = [];
});
$("button.setScope10y").click(function () {
$.ajax({url: "readsensor.php?sensor=1&property=1&aggregate=2&period=4&scope=10y&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=4&scope=10y&color=1", type: "GET", dataType: "json", success: onDataReceived });
data = [];
});
var updateLegendTimeout = null;
var latestPosition = null;
function updateLegend() {
updateLegendTimeout = null;
var pos = latestPosition;
var axes = plot.getAxes();
if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max || pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) {
// window.alert("X: " + pos.x + " XMIN:" + axes.xaxis.min + " XMAX:" + axes.xaxis.max + "\nY: " + pos.y + " YMIN:" + axes.yaxis.min + " YMAX:" + axes.yaxis.max );
return;
}
var i, j, dataset = plot.getData();
for (i = 0; i < dataset.length; ++i) {
var series = dataset;
// Find the nearest points, x-wise
for (j = 0; j < series.data.length; ++j) {
if (series.data[j][0] > pos.x) {
break;
}
}
// Now Interpolate
var y,
p1 = series.data[j - 1],
p2 = series.data[j];
if (p1 == null) {
y = p2[1];
} else if (p2 == null) {
y = p1[1];
} else {
y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);
}
// window.alert(i + " " + series.label );
legends.eq(i).text(series.label.replace(/\(.*/, "(" + y.toFixed(1) + "°C)" ));
// legends.eq(i).text(series.label.replace(/.*C.*/, "c" ));
}
}
$("#placeholder").bind("plothover", function (event, pos, item) {
latestPosition = pos;
if (!updateLegendTimeout) {
updateLegendTimeout = setTimeout(updateLegend, 50);
}
});
});
</script>
</body>
</html>
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 08 okt 2016, 12:05
av flyvert
Hur har det gått med Flot-hackandet P-G?
Håller själv på med lite fintrimmning, som tex denna bild som visar utomhustemperatur vs fjärrvärmeförbrukning.

- Utomhustemperatur vs fjärrvärmeförbrukning
Punkterna är lägstatemperaturer på dygnet.
Min lösning bygger på att man i databegäran från Flot anger hur datat skall behandlas, tex färg, axel, linje/punkt/stapel.
$("button.setScope3mo").click(function () {
$.ajax({url: "readsensor.php?sensor=3&property=5&aggregate=1&period=3&scope=3mo&type=bars&axis=2&color=0", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=2&period=3&scope=3mo&axis=1&color=1", type: "GET", dataType: "json", success: onDataReceived });
$.ajax({url: "readsensor.php?sensor=8&property=1&aggregate=3&period=3&scope=3mo&type=points&axis=1&color=1", type: "GET", dataType: "json", success: onDataReceived });
data = [];
});
Notera hur parametrarna jag passar i URLen skiljer för de tre datamängderna som hämtas till tremånadersbilden ovan
readsensor.php?sensor=3&property=5&aggregate=1&period=3&scope=3mo&type=bars&axis=2&color=0
readsensor.php?sensor=8&property=1&aggregate=2&period=3&scope=3mo&axis=1&color=1
readsensor.php?sensor=8&property=1&aggregate=3&period=3&scope=3mo&type=points&axis=1&color=1
Tex aggregate 2 är medelvärdet medan aggregate 3 är minvärde; dessa värden räknas fram av cronjob på tim, dygn, vecko och månadsbasis för att göra det enklare att hämta ut datat när man t.ex. vill ha ett max eller minvärde. Medel sparar på hel timme, osv, medan min/max sparas med den tidpunkten som värdet inföll med. Enkelt att ställa frågan;
när var det som kallast i januari och som varmast i juli.
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 14 okt 2016, 19:49
av P-G
Jag har inte haft tid. Men skall gå igenom din kod nu.
Återkommer med resultat.
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 22 okt 2016, 13:17
av P-G
Jag har fått tiden att fungera i grafen
Det var att jag hade fått in en mode för mycket.
Jag har nu tittat på din sida med olika tidsintervall.
Det jag saknar är din readsensor.php för att hämta data från MySql
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 25 okt 2016, 20:00
av flyvert
Hej P-G, var på annat håll i helgen men jag har nu bifogat den readsensor.php jag kör för närvarande (var tvungen att ändra filändelsen då forummotorn inte accepterar .php).
Tips: använd
curl eller liknande för att se vad readsensor gräver upp från databasen innan du "dockar" med Flot o Javaskriptet.
Observera; skriptet är fortfarande "ett snabbhack" jag inte är helt nöjd o färdig med.
$ curl "192.168.1.121/readsensor.php?sensor=1&property=1&aggregate=2&period=2&scope=1d&color=0"
{
"label": "Inomhus - Temp (°C)",
"data": [[1477332000000,21.3969],[1477335600000,21.4583],[1477339200000,21.451],[1477342800000,21.4906],[1477346400000,21.5312],[1477350000000,21.5823],[1477353600000,21.5573],[1477357200000,21.5229],[1477360800000,21.499],[1477364400000,21.475],[1477368000000,21.4271],[1477371600000,21.3604],[1477375200000,21.4104],[1477378800000,21.4229],[1477382400000,21.324],[1477386000000,21.2365],[1477389600000,21.1656],[1477393200000,21.1052],[1477396800000,21.051],[1477400400000,21.0115],[1477404000000,21.0073],[1477407600000,20.9698],[1477411200000,20.9385],[1477414800000,20.9688]],
"color": 0
}
Om du pillar in "type=bars" får du samma JSON data, men med lite mer jox på slutet som gör att Flot ritar staplar istället för att dra linjer
curl "192.168.1.121/readsensor.php?sensor=1&property=1&aggregate=2&period=2&scope=1d&color=0&type=bars"
{
"label": "Inomhus - Temp (°C)",
"data": [[1477332000000,21.3969],[1477335600000,21.4583],[1477339200000,21.451],[1477342800000,21.4906],[1477346400000,21.5312],[1477350000000,21.5823],[1477353600000,21.5573],[1477357200000,21.5229],[1477360800000,21.499],[1477364400000,21.475],[1477368000000,21.4271],[1477371600000,21.3604],[1477375200000,21.4104],[1477378800000,21.4229],[1477382400000,21.324],[1477386000000,21.2365],[1477389600000,21.1656],[1477393200000,21.1052],[1477396800000,21.051],[1477400400000,21.0115],[1477404000000,21.0073],[1477407600000,20.9698],[1477411200000,20.9385],[1477414800000,20.9688]]
,"bars": { "show": "true", "barWidth": 1440000, "align": "center" },
"color": 0
}
Har spenderat mycket tid på att avlusa felaktigt placerade hakparenteser och avsaknad av "dubbelfnuttar" här o där!
Det finns mycket outnyttjat jag vill addera, men tiden har inte riktigt räckt till...
/f
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 26 okt 2016, 07:32
av motoz
Utan att vara speciellt insatt i sql eller php så ser ditt readsensor.php skript ut att vara vidöppet för sql-injection attacker så lägg inte ut webbsidan åtkomlig på internet.
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 26 okt 2016, 21:34
av flyvert
motoz skrev:Utan att vara speciellt insatt i sql eller php så ser ditt readsensor.php skript ut att vara vidöppet för sql-injection attacker så lägg inte ut webbsidan åtkomlig på internet.
De ä tur a man gillar att pilla o joxa med diverse då...
https://blog.m.nu/gastblogg-att-satta-u ... ver-hemma/
Re: Behöver lite hjälp att komma igång med "flot"
Postat: 27 okt 2016, 07:26
av motoz
Openvpn är ju fint, men för andra intresserade användare av readsensor.php kan det vara bra att veta att vem som helst som har tillgång till webbsidan kan tex radera hela databasen (klassiskt exempel:
https://xkcd.com/327/ )
'Prepared statements' lär vara bästa sättet att eliminera sql-injection
http://php.net/manual/en/pdo.prepared-statements.php