Опрос


Что для Вас Умный Дом?


Результаты


Реклама


JpGraph. Рисуем графики температуры

24/11/2008 17:13:32

Подключив температурные датчики DS18B20 к компьютеру, у меня появилась возможность не только отображать текущие значения, но и сохранять показания в базе данных. Ведь в этом и заключается преимущество компьютера перед обычным термометром, в возможности сохранять, обрабатывать и анализировать полученные данные. Первым делом я стал выводить справочную информацию по каждому датчику о максимальной и минимальной температуре за сутки, за месяц. Перепад температуры за месяц. Самый холодный и теплый день в месяце, в году. Однако интереснее было бы увидеть изменение показаний визуально, нарисовать график.

PHP, конечно, имеет полный набор базового функционального инструментария для работы с изображениями, но проще взять уже готовую библиотеку. Немного покапавшись в залежах Интернета и, учитывая что график должен строиться по большому массиву значений (температурные показания снимаются каждые 5 минут), я решил воспользоваться библиотекой JpGraph. При скачивании нужно только иметь ввиду, что существует библиотека отдельно для 5-ой версии PHP и отдельно для 4-ой версии. Необходимо распаковать скаченную библиотеку в любое доступное для php-скриптов место.

У меня уже был основной индексный файл, который представлял собой лицо "Умного Дома". Напомню, что для удобства программирования некоторых интерактивных вещей я решил использовать jQuery.

<scripT type="text/javascript" src="jquery.js"></script>
<scripT type="text/javascript">

$(document).ready(
function()
{
    // Обновление графика каждые 5 минут
    var timer = window.setInterval(
    function()
    {
	$('#temp_in').attr('src', '/data.php');
    }, 300000);
}
)
</script>                                                              

Температура в доме:
<img id="temp_in" src="/data.php">
?>

Теперь создаем файл data.php и пишем в него примерно следующее:

<?
// Подключаем библиотеку
include ("jpgraph/jpgraph.php");
include ("jpgraph/jpgraph_line.php");

// Пишем SQL-запрос к базе
// Структура базы может быть разной, поэтому заменю его тестовыми значениями
$ydata = array("2.5", "2.7", "2.8", "3.0");
$xdata = array("12:00", "12:05", "12:10", "12:15");

$graph = new Graph(450,200,"auto");
$graph->SetScale("textlin");
$graph->SetMarginColor('white');
$graph->SetFrame(true,'#B3BCCB', 1);
$graph->SetTickDensity(TICKD_DENSE);
$graph->img->SetMargin(50,20,20,60);
$graph->title->SetMargin(10);
$graph->xaxis->SetTickLabels($xdata);
$graph->xaxis->SetLabelAngle(90);
$graph->xaxis->SetPos('min');

// Обычно значений много, не менее 250 в сутки, 
// поэтому нельзя выводить все значения из массива $xdata на шкалу X
// Это будет сильным нагромождением, поэтому я вывожу каждое 30-е значение.
$my_interval = ceil($i / 30);
$graph->xaxis->SetTextTickInterval($my_interval);

$lineplot=new LinePlot($ydata);
$graph->Add($lineplot);
$graph->Stroke();

?>

В результате у меня получилось примерно следующее.


Автор: Andrey_B
Любое использование материалов сайта возможно только с разрешения автора и с обязательным указанием источника.



Добавить комментарий:



Сортировка комментариев: Последние сверху | Первые сверху

2016-10-24 18:21:38 | VolkArti
Андрей, извините за беспокойство, проверил php5-gd установлена, на форуме не могу найти информацию о причинах надписи - src="/192.168.10.60/graph2.php?dev_cl=el_p&1577821105" alt="Изображение «/192.168.10.60/graph2.php?dev_cl=el_p&1577821105» не может быть показано, так как содержит ошибки.">


2016-10-24 00:19:33 | Andrey_B
VolkArti, причин тому может быть масса. Например, не установлена или не подключена библиотека php-gd. Кстати, все эти вопросы многократно обсуждались на форуме.


2016-10-23 23:03:45 | VolkArti
Андрей, во всех графиках изображения нет, выводиться надпись
src="/192.168.10.60/graph2.php?dev_cl=el_p&1577821105" alt="Изображение «/192.168.10.60/graph2.php?dev_cl=el_p&1577821105» не может быть показано, так как содержит ошибки.">


2014-09-29 20:03:41 | Alex
Друзья, помогите разобраться в чем проблема. Гугл и Яндекс результатов не дал, следующих код:

$data = mysql_query (" value, time lighttest");

while ($row=mysql_fetch_array($data)) {
$ydata[] = $row['value'];
$xdata[] = $row['time'];
}

$graph = new Graph(800, 500, "auto");
$graph->SetScale("textlin");
$lineplot = new LinePlot($ydata, $xdata);

$graph->Add($lineplot);
$lineplot->SetWeight(3);

$graph->Stroke();

Выдает следующую ошибку: "Error: 25070 Either X or Y data arrays contains non-numeric values. Check that the data is really specified as numeric data and not as strings"

Поле time является типом 'time', а поле value - 'numeric', почему jpgraph ругается на то что одно из полей не числовое понять не могу.
Заранее благодарен.


2012-02-14 00:48:47 | danag
При запуске скрипта выдается ошибка JpGraph Error: 25064
Minor or major step size is 0. Check that you haven't got an accidental SetTextTicks(0) in your code. If this is not the case you might have stumbled upon a bug in JpGraph. Please report this and if possible include the data that caused the problem


2011-12-13 17:43:49 | ruslan
лучше использовать для графиков библиотеку d3.js


2011-11-17 15:28:02 | Владимир
Здравствуйте, Андрей!
Рекомендую обратить внимание на открытую JS библиотеку jquery.plot:
/code.google.com/p/flot/
Примеры работы: /people.iola.dk/olau/flot/examples/
Спасибо за мысли, реализации и опыт! Спасибо за сайт!


2011-10-18 14:02:47 | THK
sue&241;o
Для решения поставленной задачи, я "подготавливаю" данные для осей XY.
Сначала формирую массив для оси Х, с метками времени за установленный период, а затем читаю доступные данные из базы и сравниваю дату и время каждого значения с расчетными.
Если значение для текущей расчетной даты отсутствует, записываю в качестве значения по оси Y 'x' или '-'.
'х' - это пропуск значения
'-' - это интерполяция пропущенных значений

Короче вот кусочек кода:

/ Сформировать массив с "пропуском" несуществующих в базе значений.
/ Ищем элемент массива со временем >= времени записи в базе.
while ($DataArrX[$CurData] < $DBTime and $CurData <= count($DataArrX)){
$DataArrY[$CurData] = 'x'; / По оси Y - "пустые" значения. ('-' апроксимация значений).
$CurData++;
}

PS Если нужны подробности, создайте тему на форуме и я выложу скрипты. На словах всего не расскажешь. :)


2011-10-18 11:42:07 | Andrey_B
Лично я ничего с этим не делаю. А зачем с этим нужно что-то делать? Построение графиков - это визуальное представление данных для человека. А человек разберется. Если уж очень хочется, можно восполнять недостающие данные каким-либо значением - так делает MRTG, но график становится еще менее красивым, а "дополнительные" данные не несут какой-либо полезной информации. Разве что сохраняется временная шкала. Восполнять данные можно как в момент опроса 1-wire сети, так и в момент непосредственного построения графика.
Более сложной проблемой является ситуация не построения графиков, а использования данных, где отсутствуют нормальные значения. Например, температурное регулирование. Если у нас "отвалится" датчик в помещении, то с точки зрения алгоритма (вывести среднюю температуру за 30 минут) температура внутри 0 градусов, а значит нужно срочно включать котел. В этой ситуации нужно обязательно проверять, "0" получился из данных или из их отсутствия. Если последнее - алгоритм должен формировать уведомление и приостанавливать свою работу.


2011-10-18 01:47:34 | sue&241;o
Андрей, подскажите, как вы боретесь с ситуациями когда в данных возникают дырки. К примеру вылетела сеть 1-wire и пару часов не записывалось. Jpgraph почему-то такие вещи не отслеживает и склеивает график как есть с пропуском этих часов.


2011-03-31 16:10:30 | Andrey_B
Ставр, графики красивые - спору нет, да не про нас. Это он-лайн сервис для отправки показаний датчиков на сервер Meteoplug. И графики формируются там, у них же... Никаких библиотек они не предоставляют. Это не наш подход. ;)


2011-03-31 15:49:03 | Ставр
По по воду вывода графиков... наткнулся на интересный вывод графиков (похоже на Флеше)
wiki.meteoplug.com/Gallery


2011-03-03 22:24:37 | Andrey_B
Олег, я посмотрел у себя и не нашел графиков, нарисованных посредством jpgraph, на которых были бы надписи. А в чем проблема? Вроде бы там нет никаких сложностей.


2011-03-03 14:38:52 | Oleg
Еще вопросик...
Вывод надписей на графике как Вы делали? Средствами JpGraph (graph->title->Set) или как-то по-другиму... Можете небольшой примерчик сбросить как у Вас сделано?


2011-03-03 10:30:40 | Oleg
Да, спасибо, так все ОК.


2011-03-02 16:56:28 | Andrey_B
Олег, все правильно. В статье был опубликован неправильный код. Странно, что никто это раньше не заметил. Поправил. Попробуйте, так.


2011-03-02 15:39:47 | Oleg
Здравствуйте,

Никак не получается вывести график...

В head следующее:

script type="text/javascript" src="js/jquery.js"/script
script type="text/javascript"

$(document).ready(function(){
/ "Инициализируем" div
$.get("data.php?", function(data){
$("g_temp_in").html(data);
});
});
/script

В body:
Температура в доме:
div id="g_temp_in"/div

Получаю что-то типа:

"&65533;PNG  &65533;&65533;&65533; IHDR&65533;&65533;&65533;&65533;&65533;&65533;&65533;&65533;&65533;&65533;&65533;v&65533;&65533;&65533; jIDATx&65533;&65533;&65533;A&65533;&65533;F&65533;,}&65533;&65533;&65533;&65533;&65533;m&65533;&65533;&65533;&65533;+T_&65533;f&65533;W&65533;&65533;"&65533;"...

То есть, вместо картинки я так понимаю ее текстовый вывод... А как же получить картинку?

P.S. Кстати у Вас в статье ошибка... не там запетай где нужно и не закрывается div:
"Температура в доме:
div id="g_temp_in/div";
?>"


2010-09-23 15:33:11 | Борис
Спасибо за помощь, все получилось, проблема была в периоде, я брал все значения из базы, ограничил диапазон сутками и все отобразилось правильно.


2010-09-23 12:59:38 | Andrey_B
Борис, из вашего кода не совсем ясно как вы используете полученные из базы данные в массиве $xdata. Ось X (время) логически едина для всех графиков и задается одним массивом. Если показания с разных датчиков взяты в разное время, то и второй график ляжет некорректно с точки зрения анализа графиков с позиции времени. Необходимо либо как-то нормализовать время (например усреднением), либо использовать вторую шкалу X, независимую от первой. Но я не уверен, поддерживается ли такой механизм в библиотеке jpgraph.
Это если я правильно понял вашу проблему...


2010-09-23 11:19:58 | Борис
Проблема в xdata, есть таблица в Mysql с полями id, name - номер датчика, value - температура, data - время измерения, я пробовал как Вы посоветовали, но значения по оси x смещаються.
$data1 = mysql_query (" value, date temper name like ('10.FE8EDD010800')");
$data = mysql_query (" value, date temper name like ('28.B7AB69020000')");

while ($row=mysql_fetch_array($data)) {
$ydata[] = $row['value'];
$xdata[] = $row['date'];
}

while ($row=mysql_fetch_array($data1)) {
$ydata1[] = $row['value'];
$xdata[] = $row['date'];
}
/ Create a line pot
$lplot = new LinePlot($ydata);
$lplot->SetWeight(2);
$lplot->SetColor('7070FE');
$lplot1 = new LinePlot($ydata1);
$lplot1->SetWeight(2);
$lplot1->SetColor('7070FE');

/Add plot
$graph->Add($lplot);
$graph->Add($lplot1);


2010-09-22 22:24:13 | Andrey_B
Борис, это элементарно!
Обратите внимание на строки

$lineplot=new LinePlot($ydata);
$graph->Add($lineplot);

Так вот мы можем вывести показания с неограниченного количества датчиков следующим образом:

$lineplot=new LinePlot($ydata);
$lineplot1=new LinePlot($ydata1);
$graph->Add($lineplot);
$graph->Add($lineplot1);

где $ydata, $ydata1 и т.д. массив значений с разных датчиков.


2010-09-22 18:55:55 | Борис
А как вывести показания нескольких датчиков на один график?