[Модификация] Строим графики Highstock

Вносятся изменения в файлы или устанавливаются доп программы

Модераторы: immortal, newz20

Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

[Модификация] Строим графики Highstock

Сообщение Bagir »

Слова особенно не нужны, на скрине все видно. Уверен, что многие давно хотят это получить. Постараюсь написать по проще.
Изображение
1. Из обновления от 13.03.2015, которое уже выложено на github нам нужно, что бы при запуске сценариев не выводилась первой строка Running script:
Подробно посмотреть об этом можно тут
А если вкратце, то смотрим файл \objects\index.php, ищем строку echo "\nRunning script: ".$script; и комментируем ее //

2. Создайте новый сценарий с именем jconhs

Код: Выделить всё

 // Получить имя и проверить
 if ( isset($params['name'])  ) { $name = $params['name']; } else { returm; }
 // Разбить на объект и свойство
 $name = explode('.', $name);

 // Получить объект по имени
 $obj=getObject($name[0]); 
 // Получить id свойства
 $prop_id=$obj->getPropertyByName($name[1], $obj->class_id, $obj->id);
 // Получаем VALUE_ID для следующей таблицы
 $pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$obj->id."'");
 // Получаем таблицу
 $arr_s = SQLSelect("SELECT UNIX_TIMESTAMP(ADDED) as ADDED, VALUE FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' ORDER BY ADDED");

 // Собрать структуру JSON
 $st = $params['callback'].'([';
 foreach($arr_s as $s) {
   if ($f) { $st .=','; }
   $st .= '['.$s['ADDED'].'000,'.$s['VALUE'].']' ;
   $f=1;
 }
 $st .= '])';

 // Ответ
 echo ($st); 


3. Создайте домашнюю страницу с кодом
КодSPOILER_SHOW

Код: Выделить всё

<script type="text/javascript" src="../../highcharts/js/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="../../highcharts/js/highstock.js"></script>
<script type="text/javascript">

$(function () {
    var seriesOptions = [],
          obsss = 0,
          seriesCounter = 0,
          timeback = 0,
          names = ['кухня','гостиная','спальня','холл','кабинет'], 
          sensornames = ['KitchenArea.Temperature', 
                                    'Livingroom.Temperature', 
                                    'Bedroom.Temperature',
                                    'HallArea.Temperature',
                                    'OfficeRoom.Temperature'];

    Highcharts.setOptions({
        lang: {
            months: ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль', 
                          'Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],

            shortMonths: ['Янв','Фев','Мар','Апр','Май','Июн','Июл', 
                                     'Авг','Сен','Окт','Ноя','Дек'],

            weekdays: ['Вск','Пнд','Втр','Срд','Чтв','Птн','Сбт'],

            rangeSelectorZoom: 'Маcштаб',
            rangeSelectorFrom: 'От',
            rangeSelectorTo: 'До',
            thousandsSep: ' '
        },
            global: {
                useUTC: false
            }
    });


    // create the chart when all data is loaded
    createChart = function () {
        $('#container').highcharts('StockChart', {
            rangeSelector: {
                buttons: [{ type: 'hour',    count: 1, text: '1h' },
                               { type: 'day',     count: 1, text: '1d' },
                               { type: 'day',     count: 2, text: '2d' },
                               { type: 'week',   count: 1, text: '1w' },
                               { type: 'month', count: 1, text: '1m' },
                               { type: 'month', count: 6, text: '6m' },
                               { type: 'year',    count: 1, text: '1y' },
                               { type: 'all', text: 'All' }],
                selected: 1  // Какая кнопка выбрана по умолчанию
            },
  
            title: { text : 'График температур в доме'},
            legend: { enabled : true,
                           layout : 'horizontal',
                           align : 'center',
                           verticalAlign : 'top',
                           borderWidth: 0,
                           x : 0,
                           y : 20 },

            xAxis : {
                minRange: 3600 * 1000 // one hour
            },

            yAxis: {
                title: {
                    text: 'Температура (°C)'
                }
            },

            plotOptions: {
                series: {
                    lineWidth: 1,
                    point: {
                        events: {
                            'click': function () {
                                if (this.series.data.length > 1) {
                                    this.remove();
                                }
                            }
                        }
                    }
                }
            },

            exporting: {
                enabled: false
            },

            series: seriesOptions
        });
    };

    $.each(names, function (i, name) {
        $.getJSON('/objects/?script=jconhs&name='+sensornames[i]+'&callback=?', function (data) {

            seriesOptions[i] = {
                name: name,
                data: data,
                type: 'spline'
            };

            // As we're loading the data asynchronously, we don't know what order it will arrive. So
            // we keep a counter and create the chart when all the data is loaded.
            seriesCounter += 1;

            if (seriesCounter === names.length) {
                createChart();
            }
        });
    });

});
</script>

<div id="container" style="height: 500px; min-width: 500px"></div>
4. Замените в коде Названия и имена Объект.Свойство на свои. Попробуйте для начала с одним графиком. Потом добавьте второй, и так далее. Не нарушайте структуру при редактировании!

Код: Выделить всё

          names = ['кухня','гостиная','спальня','холл','кабинет'], 
          sensornames = ['KitchenArea.Temperature', 
                                    'Livingroom.Temperature', 
                                    'Bedroom.Temperature',
                                    'HallArea.Temperature',
                                    'OfficeRoom.Temperature'];
 
Основная причина, по которой графики могут не строиться, это битые данные в истории свойства.
Тема с этими графиками подробно расписана тут http://smartliving.ru/forum/viewtopic.p ... 140#p14843 С тех пор много всего поменялось. Тут я выложил только самое основное.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
PAV
Сообщения: 970
Зарегистрирован: Пт дек 06, 2013 11:30 am
Откуда: Москва

Re: Строим графики Highstock

Сообщение PAV »

Bagir писал(а): Основная причина, по которой графики могут не строиться, это битые данные в истории свойства.
А как это можно исправить?
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Строим графики Highstock

Сообщение Bagir »

Посмотреть историю и самому удалить кривые данные. Например пустые значения вообще без цифр. У меня были такие, когда метод датчика растрепал )) Можно было бы добавить обработку в файл, который формирует jcon, но это сильно увеличит его время работы. Кстати, в скором будущем перенесу все содержимое этого файла в сценарий, и из html кода графиков буду обращаться уже к сценарию, а не к файлу. Не знаю почему я так сразу задумал. Наверное после темы MegaD )) Его может быть тоже можно перенести в сценарий. Надо будет попробовать.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
PAV
Сообщения: 970
Зарегистрирован: Пт дек 06, 2013 11:30 am
Откуда: Москва

Re: Строим графики Highstock

Сообщение PAV »

А можно вот на пальцах объяснить?
Я полез в phpmyadmin - там черт ногу сломит, я даже простым способом не смог сделать сортировку по определенному свойству. Все запросами, а это ужас, как неудобно.
Пришлось экспортировать и смотреть в экселе.
Может есть пути более логичные, чтобы сразу в базе отсортировать свойство (температуру например) по значениям и выявить ошибки?
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Строим графики Highstock

Сообщение Bagir »

В phpmyadmin очень удобно делать простые запросы чтобы смотреть данные. Конечно для этого нужно немножечко знать sql. Но если хочется способ по проще, он есть. Если для постройки графиков Вы использовали мой jsonp.php, то в браузере наберите запрос
http://localhost/jsonp.php?name=OfficeRoom.Temperature
где OfficeRoom.Temperature это нужное Объект.Свойство
В итоге получите весьма читаемый json, пригодный к анализу например в excel с помощью фильтров и функций для работы с текстом.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Строим графики Highstock

Сообщение Bagir »

Заменил файл jsonp.php на сценарий jconhs. Файл jsonp.php теперь больше не нужен, и его можно удалить!
В html коде надо везде поменять

Код: Выделить всё

$.getJSON('../../jsonp.php?name='+sensornames[i]+'&callback=?', function (data) { 
на

Код: Выделить всё

$.getJSON('/objects/?script=jconhs&name='+sensornames[i]+'&callback=?', function (data) { 
Еще там была лишняя неиспользуемая функция function afterSetExtremes(e) Ее тоже можно удалить. Смотрите новый код в первом сообщении.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
visitor2100
Сообщения: 19
Зарегистрирован: Пт фев 20, 2015 5:24 pm

Re: Строим графики Highstock

Сообщение visitor2100 »

Bagir, после недели мучений, все работает. Спасибо!
eygen
Сообщения: 393
Зарегистрирован: Чт сен 25, 2014 5:37 pm
Откуда: Екатеринбург

Re: Строим графики Highstock

Сообщение eygen »

Спасибо за ликбез! Запустилось все за 5 минут. Не подскажете как несколько таких графиков на одну страницу разместить?
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Строим графики Highstock

Сообщение Bagir »

Да можно конечно. Правда не силен я в функциях на javascript, и могу сделать не красиво, но работать будет )) Сейчас чего нибудь нарисуем.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич

Re: Строим графики Highstock

Сообщение Bagir »

скринSPOILER_SHOW
Изображение
кодSPOILER_SHOW

Код: Выделить всё

<script type="text/javascript" src="../../highcharts/js/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="../../highcharts/js/highstock.js"></script>
<script type="text/javascript">

$(function () {
    var seriesOptions = [],
          obsss = 0,
          seriesCounter = 0,
          timeback = 0,
          names = ['кухня','гостиная','спальня','холл','кабинет'], 
          sensornames = ['KitchenArea.Temperature', 
                                    'Livingroom.Temperature', 
                                    'Bedroom.Temperature',
                                    'HallArea.Temperature',
                                    'OfficeRoom.Temperature'];

    Highcharts.setOptions({
        lang: {
            months: ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль', 
                          'Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],

            shortMonths: ['Янв','Фев','Мар','Апр','Май','Июн','Июл', 
                                     'Авг','Сен','Окт','Ноя','Дек'],

            weekdays: ['Вск','Пнд','Втр','Срд','Чтв','Птн','Сбт'],

            rangeSelectorZoom: 'Маcштаб',
            rangeSelectorFrom: 'От',
            rangeSelectorTo: 'До',
            thousandsSep: ' '
        },
            global: {
                useUTC: false
            }
    });

    // create the chart when all data is loaded
    createChart = function () {
        $('#container').highcharts('StockChart', {


           rangeSelector: {
                buttons: [{ type: 'hour',    count: 1, text: '1h' },
                               { type: 'day',     count: 1, text: '1d' },
                               { type: 'day',     count: 2, text: '2d' },
                               { type: 'week',   count: 1, text: '1w' },
                               { type: 'month', count: 1, text: '1m' },
                               { type: 'month', count: 6, text: '6m' },
                               { type: 'year',    count: 1, text: '1y' },
                               { type: 'all', text: 'All' }],
                selected: 1  // Какая кнопка выбрана по умолчанию
            },
  
            title: { text : 'График температур в доме'},
            legend: { enabled : true,
                           layout : 'horizontal',
                           align : 'center',
                           verticalAlign : 'top',
                           borderWidth: 0,
                           x : 0,
                           y : 20 },

            xAxis : {
                minRange: 3600 * 1000 // one hour
            },

            yAxis: {
                title: {
                    text: 'Температура (°C)'
                }
            },

            plotOptions: {
                series: {
                    lineWidth: 1,
                    point: {
                        events: {
                            'click': function () {
                                if (this.series.data.length > 1) {
                                    this.remove();
                                }
                            }
                        }
                    }
                }
            },

            exporting: {
                enabled: false
            },

            series: seriesOptions
        });
    };

    $.each(names, function (i, name) {
        $.getJSON('/objects/?script=jconhs&name='+sensornames[i]+'&callback=?', function (data) {

            seriesOptions[i] = {
                name: name,
                data: data,
                type: 'spline'
            };

            // As we're loading the data asynchronously, we don't know what order it will arrive. So
            // we keep a counter and create the chart when all the data is loaded.
            seriesCounter += 1;

            if (seriesCounter === names.length) {
                createChart();
            }
        });
    });

});





$(function () {
    var seriesOptions = [],
          obsss = 0,
          seriesCounter = 0,
          timeback = 0,
          names = ['кухня', 'гостиная', 'спальня', 'кабинет'], 
          sensornames = ['KitchenArea.Humidity', 
                                    'Livingroom.Humidity', 
                                    'Bedroom.Humidity',
                                    'OfficeRoom.Humidity'];

    Highcharts.setOptions({
        lang: {
            months:   ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 
                            'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],

            shortMonths:   ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 
                                     'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],

            weekdays: ['Вск', 'Пнд', 'Втр', 'Срд', 'Чтв', 'Птн', 'Сбт'],

            rangeSelectorZoom: 'Маcштаб',
            rangeSelectorFrom: 'От',
            rangeSelectorTo: 'До',
            thousandsSep: ' '
        },
            global: {
                useUTC: false
            }
    });


    // create the chart when all data is loaded
    createChart2 = function () {
        $('#container2').highcharts('StockChart', {

            rangeSelector: {
                buttons: [{ type: 'hour',    count: 1, text: '1h' },
                               { type: 'day',     count: 1, text: '1d' },
                               { type: 'day',     count: 2, text: '2d' },
                               { type: 'week',   count: 1, text: '1w' },
                               { type: 'month', count: 1, text: '1m' },
                               { type: 'month', count: 6, text: '6m' },
                               { type: 'year',    count: 1, text: '1y' },
                               { type: 'all', text: 'All' }],
                selected: 1  // Какая кнопка выбрана по умолчанию
            },
  
            title: { text : 'График влажности воздуха'},
            legend: { enabled : true,
                           layout : 'horizontal',
                           align : 'center',
                           verticalAlign : 'top',
                           borderWidth: 0,
                           x : 0,
                           y : 20 },

            xAxis : {
                minRange: 3600 * 1000 // one hour
            },

            yAxis: { title: { text: 'Влажность (%)' } },

            plotOptions: {
                series: {
                    lineWidth: 1,
                    point: {
                        events: {
                            'click': function () {
                                if (this.series.data.length > 1) {
                                    this.remove();
                                }
                            }
                        }
                    }
                }
            },

            exporting: {
                enabled: false
            },

            series: seriesOptions
        });
    };

    $.each(names, function (i, name) {
        $.getJSON('/objects/?script=jconhs&name='+sensornames[i]+'&callback=?', function (data) {

            seriesOptions[i] = {
                name: name,
                data: data
            };

            // As we're loading the data asynchronously, we don't know what order it will arrive. So
            // we keep a counter and create the chart when all the data is loaded.
            seriesCounter += 1;

            if (seriesCounter === names.length) {
                createChart2();
            }
        });
    });

});
</script>

<div id="container" style="height: 400px; min-width: 500px"></div>
<div id="container2" style="height: 400px; min-width: 500px"></div>
Код конечно для примера. Во второй группе изменены имена container2 и createChart2.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Ответить