javascript - 绘制温度的平均值

标签 javascript php mysql math graph

我有许多用于监视环境的温度传感器。最近,我不再使用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/

相关文章:

mysql - 不再支持使用旧密码进行身份验证

Javascript - 使用简写 jQuery 添加授权 header

javascript - 表级别的关键事件绑定(bind)

来自 cpanel 的 PhpMyAdmin 连接使用自定义用户

javascript - Laravel 5.6 在公共(public)文件夹中添加 javascript 库 "Page not found"

mysql - 从 linux mint 完全卸载 mysql

python - 通过SSH隧道访问远程数据库

javascript - 不使用字符串方法trim去除空格

JavaScript 无限循环

php - 如何按条件对sql结果进行排序?