Последние статьи
- Твердотельный датчик направления и скорости ветра. Эксперимент
- iPhone на стене в качестве панели управления домом
- MegaD-16M-XT - подсветка выключателей и не только
- Переделка выключателей в кнопки и мини-обзор текущего рынка
- RadSens - модульный счетчик Гейгера с интерфейсом I2C
- "U" - значит универсальный. Обзор модуля MegaD-16U-XT
- SCD4x - современная альтернатива для измерения концентрации CO2
- HTU31D - новый датчик температуры и влажности с нагревательным элементом
- Измерение коэффициента пульсации ламп с помощью MegaD-2561
- Использование солнечных панелей в качестве датчика освещенности
- Согласование датчиков с выходом типа TTL со стандартными входами контроллера
- DPS368 - датчик атмосферного давления индустриального класса повышенной точности
- DS18B20 Waterpoof - импортзамещение
- TMP117 - высокоточный датчик температуры с интерфейсом I2C
- MegaD-16R-XT - расширитель на 16 релейных выходов
- MegaD-2561-RTC V3 - больше портов, зуммер и ИОН
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
Любое использование материалов сайта возможно только с разрешения автора и с обязательным указанием источника.
Добавить комментарий:
Сортировка комментариев: Последние сверху | Первые сверху
2018-03-12 15:58:08 | Andrey_B
Алексей, различных библиотек для рисования графиков десятки, если не сотни. Можно использовать то, что понравится. Наверное, сейчас уже есть библиотеки, которые легче, удобнее, красивее, чем jpGraph.
2018-03-12 13:59:23 | Алексей
Добрый день. А вы не пробовали для отображения графиков использовать Hights ? Это бесплатный для некомерческого использования Java скрипт. Я сам только начинаю изучать тему умных домов, но интересное решение они предлагают.
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 | Борис
А как вывести показания нескольких датчиков на один график?