我有许多用于监视环境的温度传感器。最近,我不再使用RRD捕获这些图形并对其进行图形化,而是将数据存储在MySQL中并使用Chart.js进行图形化,因为它提供了用于绘制外观的多种选择,它还使我能够灵活地移动到不同的图形如果愿意的话,将来可以使用图书馆。
我的问题更多是关于什么是存储数据的最佳方法。此刻,我每分钟都会查询温度并存储所有东西。然后,我使用MySQL查询来获取以下数据:
上一小时-MySQL查询获取最近60个读数(输出60个值)
最后一天-MySQL查询平均每小时读取60个读数(输出24个值)
上周-MySQL查询将每小时读数平均为一天的平均值(输出7个值)
我真的不确定这是获取每日和每周读数的最佳方法,然后我还希望获得每月和每年的读数。
谁能建议一种更好的数据处理方式?更好的查询,因为它们在数学上非常密集,将月度读数存储在平均读数的另一个表中会更好,我应该多久对数据进行一次平均?
请帮忙! (也不确定将哪个类别放入堆栈溢出):)
最佳答案
总览
这不是一件容易的事。您正在查看许多后端工作和图形。很多图表。所以我为你做了所有。
因此,根据我的理解,您需要以下内容:
为了能够平均温度值。
为了能够对数据进行排序/按周,月等显示数据。
拥有美观,现代的交互式图表/图形。
拥有一种干净,高效,有效的数据存储和处理方式。
整个答案基于我对Flot的了解以及您将要使用的假设而定,但是,此处的大多数知识和代码都可以应用于几乎所有的javascript图表库。
1.平均值
Flot有一个Averaging Plugin,它在图形上放置一条线以表示平均值。这样,您就可以以图形方式查看温度随时间变化的平均值。我可以想象白天和黑夜之间出现正弦曲线。这对我来说足够好,但是我确实想要这个平均值的实际数字。
如果在此处稍加修改,我们可以使用Sum values from an Array链接从Flot期望的数据格式中提取平均值。我在下面做了这个。
var myData = [['2013-01-22', 0], ['2013-01-29', 1], ['2013-02-05', 21]];
var myTotal = 0; // Variable to hold your total
var myAverage = 0; // Variable to hold your average
var myNumber = 0; // Variable to hold the number of items to divide by
for(var i = 0, len = myData.length; i < len; i++) {
myTotal += myData[i][1]; // Iterate over your first array and then grab the second element add the values up
myNumber++; // This will give us the number of items we added
}
myAverage = myTotal / myNumber;
document.write(myTotal); // 22 in this instance
document.write(myNumber); // 3 in this instance (useful for knowing how many data points you have)
document.write(myAverage); // 7.3 in this instance
我不确定你是什么意思
我应该多久平均一次数据?
不知道您要删除数据点还是只想求平均值或...,但是您实际上并不需要删除数据点。平均值在上面完成。如果您迫切希望使用更少的数据点来节省空间/处理时间,则正是的Downsample Plugin删除了数据点而没有明显的差异,正是出于这个原因。
2.显示数据
再次基于基本假设,您最终将使用Flot,该函数内置于Flot中。我想您为收集的数据设置了时间戳。通过在Flot中随时间绘制图形,您可以使用按钮轻松显示一个月,两个月,最后一天……您想要的任何时间段的数据。在此示例Flot中显示了这一点。
如果您希望随着时间的推移获得更好的交互形式,请在Time Series Interaction中查找Interactivity Examples。
3.一个漂亮的图
这自然带有Flot!您可以调整不同区域的颜色,选择是否填充,但实际上它们看起来已经不错了。
4.存储和处理数据
现在,这里有三个结果,但我只涉及两个。
您将数据保留在数据库中。
您将还原为使用日志文件。
您是实时的(未涵盖)。
总览
这部分试图回答
我的问题更多是关于什么是存储数据的最佳方法。此刻,我每分钟都会查询温度并存储所有东西。然后,我使用MySQL查询来获取以下数据:
上一小时-MySQL查询获取最近60个读数(输出60个值)
最后一天-MySQL查询平均每小时读取60个读数(输出24个值)
上周-MySQL查询将每小时读数平均为一天的平均值(输出7个值)
我真的不确定这是获取每日和每周读数的最佳方法,然后我还希望获得每月和每年的读数。
谁能建议一种更好的数据处理方式?更好的查询,因为它们在数学上非常密集,因此将月度读数存储在另一个平均读数表中会更好
我个人认为,存储数据的最佳方法是使用图表库所需的确切格式。但是,如果您不实时运行,则几乎可以使用最简单的方法,并且由于您无法快速加载数百万个数据点,因此无关紧要/没有太大关系。
我假设您确实使用RRDtool日志,现在使用MySQL。对于获得每日和每周阅读的最佳方法,我认为这与MySQL不相关。后端的工作是收集,存储和呈现数据。前端,也称为Flot将为您对这些数据进行排序,并显示每日和每周的读数,如第二部分所述。这样可以使您免于这些复杂的查询。
我建议更好地使用数据的建议是,让后端不使用带有查询的数据,也不使用平均值的单独文件,而仅将其呈现给Flot,并让Flot处理数据以仅呈现数据你要。现在获取后端以图形化数据...
Flot将期望以下格式的数据:
[[timestamp, data], [timestamp, data]]
因此,让我们到达那里。
1. MySQL / PHP
好的,所以您不必费心回到日志。或者您从未使用过它们,无论哪个。
您必须使用正确的时间戳将MySQL值设置为正确的格式。嗯现在,我不知道您如何存储时间戳,因此让我们假设您已经了解了每分钟轮询数据的知识(crontab?)。我们不知道您何时开始轮询此数据,因此我们将不得不随着时间的推移进行反向工作。
首先,获取数据。
我很快找到了这个Flot。下面的代码将从MySQL表中获取数据并将其写入文件。便利。我正在假设每个值都换一行。
<?php
$pdo = new PDO(...);
$results = $pdo->query("SELECT * FROM myTable INTO OUTFILE 'data.txt'");
$dummy = $result->fetchAll();
?>
对。现在将数据存储在文件中,用于时间戳记。
<?php
$time = time() * 1000;
$file = fopen("data.txt", "w+");
foreach(file("data.txt") as $line) {
if ($file > 0) {
$write = ", [" . $time . ", " . $line . "]";
fwrite($file, $write);
} else {
$write = "[" . $time . ", " . $line . "]";
fwrite($file, $write);
}
$time = $time - 60000;
}
fclose($file);
?>
好吧,让我逐行解释一下。
javascript库预期的纪元时间以毫秒为单位,但是PHP以秒为单位显示纪元时间,因此将其乘以一千。
接下来,我们要将您的数据输出写入文件。这很容易在Export MySQl Table To File中定义,并在以后为您提供更大的灵活性。因此,我们提早打开文件,以表示每次解析新行时它都会打开。
然后,我们逐行浏览并将数据以适当的格式写入文件,并带有时间戳。假设数据是刚刚收集的。
然后,每次迭代都返回一分钟(60000毫秒),因此它在时间上向后工作。 Flot将为您处理。
然后,我们关闭文件。
之后,Flot可以从文件读取数据。做得很好。
2. PHP /日志
好的,这很有趣。您已恢复使用我完全假定的RRDtool日志格式。
我将通过下面的代码向您介绍。
<?php
$file = fopen("log.txt", "r");
$tempOneFile = fopen("tempOne.txt", "w+");
$tempTwoFile = fopen("tempTwo.txt", "w+");
while ($first = fscanf($file, "%s\t%s\t%s\n")) {
list ($timestamp, $temperatureone, $temperaturetwo) = $first;
$time = $timestamp * 1000;
if ($file > 0) {
$one = ", [" . $time . ", " . $temperatureone . "]";
$two = ", [" . $time . ", " . $temperaturetwo . "]";
$fwrite($tempOneFile, $one);
$fwrite($tempOneFile, $two);
} else {
$one = "[" . $time . ", " . $temperatureone . "]";
$two = "[" . $time . ", " . $temperaturetwo . "]";
$fwrite($tempOneFile, $one);
$fwrite($tempOneFile, $two);
}
}
fclose($file);
?>
好。因此,也许有更好的处理数据的方法,但是我个人喜欢使用正确格式的数据创建文件。它易于阅读,并且非常灵活。
对日志文件执行此操作。
3.实时/ Nodejs
从PHP / MySQL到实时javascript和Web套接字等等,起初它是令人生畏的。但这还不错。基本上,您是通过Web套接字流式传输数据的。但是我不会介绍这个,因为它不是您所需的温度。
结论
我希望这个冗长的答案能回答您的问题。下一步实际上是使用Flot将数据转换为图形。在整个答案中,我对您的数据格式做了很多假设。如果某项不起作用,有所不同,您不知道如何使用它或类似的东西,请不要害怕发表评论。谢谢!
关于javascript - 绘制温度的平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34588908/