Страница 1 из 12

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

Добавлено: Чт фев 26, 2015 7:33 pm
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. Создайте домашнюю страницу с кодом
КодПоказать

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

<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 С тех пор много всего поменялось. Тут я выложил только самое основное.

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

Добавлено: Ср мар 11, 2015 11:01 am
PAV
Bagir писал(а): Основная причина, по которой графики могут не строиться, это битые данные в истории свойства.
А как это можно исправить?

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

Добавлено: Ср мар 11, 2015 1:05 pm
Bagir
Посмотреть историю и самому удалить кривые данные. Например пустые значения вообще без цифр. У меня были такие, когда метод датчика растрепал )) Можно было бы добавить обработку в файл, который формирует jcon, но это сильно увеличит его время работы. Кстати, в скором будущем перенесу все содержимое этого файла в сценарий, и из html кода графиков буду обращаться уже к сценарию, а не к файлу. Не знаю почему я так сразу задумал. Наверное после темы MegaD )) Его может быть тоже можно перенести в сценарий. Надо будет попробовать.

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

Добавлено: Чт мар 12, 2015 12:20 pm
PAV
А можно вот на пальцах объяснить?
Я полез в phpmyadmin - там черт ногу сломит, я даже простым способом не смог сделать сортировку по определенному свойству. Все запросами, а это ужас, как неудобно.
Пришлось экспортировать и смотреть в экселе.
Может есть пути более логичные, чтобы сразу в базе отсортировать свойство (температуру например) по значениям и выявить ошибки?

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

Добавлено: Чт мар 12, 2015 5:09 pm
Bagir
В phpmyadmin очень удобно делать простые запросы чтобы смотреть данные. Конечно для этого нужно немножечко знать sql. Но если хочется способ по проще, он есть. Если для постройки графиков Вы использовали мой jsonp.php, то в браузере наберите запрос
http://localhost/jsonp.php?name=OfficeRoom.Temperature
где OfficeRoom.Temperature это нужное Объект.Свойство
В итоге получите весьма читаемый json, пригодный к анализу например в excel с помощью фильтров и функций для работы с текстом.

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

Добавлено: Пт мар 13, 2015 12:26 am
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) Ее тоже можно удалить. Смотрите новый код в первом сообщении.

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

Добавлено: Сб мар 14, 2015 9:45 am
visitor2100
Bagir, после недели мучений, все работает. Спасибо!

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

Добавлено: Вс мар 22, 2015 5:44 pm
eygen
Спасибо за ликбез! Запустилось все за 5 минут. Не подскажете как несколько таких графиков на одну страницу разместить?

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

Добавлено: Вс мар 22, 2015 7:08 pm
Bagir
Да можно конечно. Правда не силен я в функциях на javascript, и могу сделать не красиво, но работать будет )) Сейчас чего нибудь нарисуем.

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

Добавлено: Вс мар 22, 2015 7:21 pm
Bagir
скринПоказать
Изображение
кодПоказать

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

<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.