Страница 1 из 2
Предыдущее значения свойства с историей
Добавлено: Сб сен 20, 2014 12:02 am
Bagir
Как получить? Вероятно SQL запросом. Это я мог бы, но никак не разберусь в структуре базы. Таблицу нашел. Должно быть это phistory. Но как узнать VALUE_ID? Нашел таблицу объектов и свойств. Нашел где записано количества дней истории. Но как узнать VALUE_ID так и не понял.
Помогите запросом, или инфой как получить VALUE_ID из таблицы phistory.
Re: Предыдущее значения свойства с историей
Добавлено: Сб сен 20, 2014 7:33 am
denis
Re: Предыдущее значения свойства с историей
Добавлено: Сб сен 20, 2014 9:57 am
Bagir
Вот спасибо! Как только не пробовал искать, ничего не попадалось. И надо было же попробовать по "FROM phistory WHERE" Ну как сам не догадался... Можно получить не только последнее значение, но еще и анализировать изменения данных. Отличный пример!
Re: Предыдущее значения свойства с историей
Добавлено: Сб сен 20, 2014 11:48 am
Bagir
Сделал так:
Метод tempChanged класса tempSensors запускается у меня при изменении свойства temp. Это удобно для слинкованных датчиков. У свойства temp есть история. Добавил метод код для определеня куда изменяется температура.
Код: Выделить всё
// Внимание! История свойства должна храниться!!!
// получить предыдущее значение температуры из SQL базы и сравнить с новым.
//Получить ид свойства
$prop_id=$this->getPropertyByName('temp', $this->class_id, $this->id);
//Получаем VALUE_ID для следующей таблицы
$pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$this->id."'");
// Получаем предыдущую запись
$prevRecord = SQLSelectOne("SELECT * FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' ORDER BY ADDED DESC LIMIT 1 , 1");
// Округление до 1 цифры
$old_temp=round($prevRecord[VALUE], 1);
$cur_temp = round($this->getProperty('temp'), 1);
//Сравнение
if ($cur_temp>$old_temp) {
$d=1;
} elseif ($cur_temp<$old_temp) {
$d=-1;
} else {
$d=0;
}
$this->setProperty('direction',$d);
Теперь у датчиков температуры на сценах есть треугольник, показывающий направление изменения температуры. Вот как то так:

При сравнении температур, можно отключить 0, тогда всегда будет сохранено последнее изменение температуры.
Код: Выделить всё
//Сравнение
if ($cur_temp>$old_temp) {
$this->setProperty('direction',1);
} elseif ($cur_temp<$old_temp) {
$this->setProperty('direction',-1);
} else {
// $this->setProperty('direction',0);
}
Re: Предыдущее значения свойства с историей
Добавлено: Сб сен 20, 2014 12:04 pm
Vit
Bagir писал(а):
Теперь у датчиков температуры на сценах есть треугольник, показывающий направление изменения температуры. Вот как то так:
Как значек изменения ниже датчика расположил?
Re: Предыдущее значения свойства с историей
Добавлено: Сб сен 20, 2014 12:20 pm
Bagir
Можно позиционировать с помощью CSS. Я там порядочно поднабрался, пока трубы рисовал, но тут я просто перед тегом, который рисует значок, поставил <br>
Re: Предыдущее значения свойства с историей
Добавлено: Вт сен 23, 2014 12:22 am
Bagir
Я уже приводил пример кода метода tempChanged. Так что сейчас только расскажу о дополнениях. Свойство direction у меня пока что используется только для элементов датчиков на сценах. Показывает направление изменения значения. Если, к примеру, взять температуру или влажность, то показания при каждом считывании датчика будут разные. Даже +- градус это нормально. В основном конечно температура гуляет на пол градуса. Соответственно стрелки изменения на датчиках тоже постоянно показывают то вверх, то вниз. А следовательно от них нет никакого прока.
Но если смотреть на среднюю величину за определенный период, то уже становится более интересно. Пока что я выбрал такие временные рамки: при периоде обновления датчика 5-10 минут, сравнить среднюю температуру за последние 30 минут, и текущую температуру. Теперь днем, когда ярко светило солнце, все стрелки на датчиках показали вверх, за исключением одного, в комнате которого было открыто окно. Там температура немного упала.
Такой подход мне понравился больше. Уже через полчаса работы котла на отопление, стрелки датчиков всех комнат дружно показывали вверх.
Вот кусок кода из tempChanged для получения средней температуры за полчасар:
Код: Выделить всё
// Получение среднего значения из истории
//Получить id свойства
$prop_id=$this->getPropertyByName('temp', $this->class_id, $this->id);
//Получаем VALUE_ID для следующей таблицы
$pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$this->id."'");
//Получаем средние значения температуры за последние 30 минут
$start_time=time()-30*60; // 30 минут
$arr_t = SQLSelectOne("SELECT avg(VALUE) as AVG_V FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'");
$avg_t=round($arr_t[AVG_V], 1);
Ранее я отключал установку свойства direction = 0, чтобы у датчика всегда была стрелка о последнем изменении температуры. Теперь, учитывая временные рамки, direction = 0 опять обрело смысл. Незначительные колебания температуры - это не повод показывать стрелку изменения.
Код: Выделить всё
// $params['t']
$this->setProperty("updated",time());
$this->setProperty("updatedTime",date("H:i",time()));
$this->setProperty("alive",1);
$ot=$this->object_title;
$alive_timeout=(int)$this->getProperty("aliveTimeOut");
if (!$alive_timeout) {
$alive_timeout=30*60;
}
clearTimeOut($ot."_alive");
setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout);
$t=round($params['t'], 1);
if (($t > 150) || ($t < -50)) {
//Некорректные данные
return;
}
// Получение среднего значения из истории
//Получить id свойства
$prop_id=$this->getPropertyByName('temp', $this->class_id, $this->id);
//Получаем VALUE_ID для следующей таблицы
$pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$this->id."'");
//Получаем средние значения температуры за последние 30 минут
$start_time=time()-30*60; // 30 минут
$arr_t = SQLSelectOne("SELECT avg(VALUE) as AVG_V FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'");
$avg_t=round($arr_t[AVG_V], 1);
$this->setProperty('temp',$t);
//Сравнение
if ($t>$avg_t) {
$d=1;
} elseif ($t<$avg_t) {
$d=-1;
} else {
$d=0;
}
$this->setProperty('direction',$d);
// Передать данные слинкованной комнате
$linked_room=$this->getProperty("LinkedRoom");
if ($linked_room) {
setGlobal($linked_room.'.Temperature', $t);
}
Re: Предыдущее значения свойства с историей
Добавлено: Чт ноя 27, 2014 11:17 pm
Vovix
Bagir писал(а):Я уже приводил пример кода метода tempChanged. Так что сейчас только расскажу о дополнениях. Свойство direction у меня пока что используется только для элементов датчиков на сценах. Показывает направление изменения значения. Если, к примеру, взять температуру или влажность, то показания при каждом считывании датчика будут разные. Даже +- градус это нормально. В основном конечно температура гуляет на пол градуса. Соответственно стрелки изменения на датчиках тоже постоянно показывают то вверх, то вниз. А следовательно от них нет никакого прока.
Но если смотреть на среднюю величину за определенный период, то уже становится более интересно. Пока что я выбрал такие временные рамки: при периоде обновления датчика 5-10 минут, сравнить среднюю температуру за последние 30 минут, и текущую температуру. Теперь днем, когда ярко светило солнце, все стрелки на датчиках показали вверх, за исключением одного, в комнате которого было открыто окно. Там температура немного упала.
Такой подход мне понравился больше. Уже через полчаса работы котла на отопление, стрелки датчиков всех комнат дружно показывали вверх.
Вот кусок кода из tempChanged для получения средней температуры за полчасар:
Код: Выделить всё
// Получение среднего значения из истории
//Получить id свойства
$prop_id=$this->getPropertyByName('temp', $this->class_id, $this->id);
//Получаем VALUE_ID для следующей таблицы
$pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$this->id."'");
//Получаем средние значения температуры за последние 30 минут
$start_time=time()-30*60; // 30 минут
$arr_t = SQLSelectOne("SELECT avg(VALUE) as AVG_V FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'");
$avg_t=round($arr_t[AVG_V], 1);
Ранее я отключал установку свойства direction = 0, чтобы у датчика всегда была стрелка о последнем изменении температуры. Теперь, учитывая временные рамки, direction = 0 опять обрело смысл. Незначительные колебания температуры - это не повод показывать стрелку изменения.
Код: Выделить всё
// $params['t']
$this->setProperty("updated",time());
$this->setProperty("updatedTime",date("H:i",time()));
$this->setProperty("alive",1);
$ot=$this->object_title;
$alive_timeout=(int)$this->getProperty("aliveTimeOut");
if (!$alive_timeout) {
$alive_timeout=30*60;
}
clearTimeOut($ot."_alive");
setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout);
$t=round($params['t'], 1);
if (($t > 150) || ($t < -50)) {
//Некорректные данные
return;
}
// Получение среднего значения из истории
//Получить id свойства
$prop_id=$this->getPropertyByName('temp', $this->class_id, $this->id);
//Получаем VALUE_ID для следующей таблицы
$pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$this->id."'");
//Получаем средние значения температуры за последние 30 минут
$start_time=time()-30*60; // 30 минут
$arr_t = SQLSelectOne("SELECT avg(VALUE) as AVG_V FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'");
$avg_t=round($arr_t[AVG_V], 1);
$this->setProperty('temp',$t);
//Сравнение
if ($t>$avg_t) {
$d=1;
} elseif ($t<$avg_t) {
$d=-1;
} else {
$d=0;
}
$this->setProperty('direction',$d);
// Передать данные слинкованной комнате
$linked_room=$this->getProperty("LinkedRoom");
if ($linked_room) {
setGlobal($linked_room.'.Temperature', $t);
}
Странно!
Я тут решил проверить работоспособность этого кода
tempChanged у себя
и обнаружил, что
$params['t'] у меня всегда равно
0
хотя значение свойства связанного с 1-wire объекта
TempSensor1.temp нормально и показывает сейчас например
24
изменил код в двух местах:
в самом начале добавил
и заменил
на
и всё стало работать правильно!
видимо у вас метод вызывается с параметром при изменении, а у меня без входящего параметра...
наверно так!
Re: Предыдущее значения свойства с историей
Добавлено: Вс ноя 30, 2014 1:44 am
Vovix
И еще, мне градиентная заливка была не нужна, а вот
direction хотел прикрутить!
Вот я так сделал без использования дополнительных состояний, прямо в коде самого значения температуры:
Код: Выделить всё
<span style="font-size:42px;font-weight:bold;
background: url(/images/%TempSensor1.direction%.gif) bottom 10px left / 20px 20px no-repeat;">
%TempSensor1.temp1%°C</span>
Re: Предыдущее значения свойства с историей
Добавлено: Пн дек 01, 2014 11:37 pm
Vovix
Еще подумал я: очень редко я вижу, что направление изменения равно 0 (т.е. как-бы температура стабильна)!
А почему?
Потому, что среднее значение за последние 0,5 часа может и отличается незначительно, например на 0,1 грудуса
и следовательно даже такое незначительное отличие предложенный алгоритм примет за какую-то тенденцию (направление), что по сути не верно!
Решение: надо, предположим, менять свойство
direction, на направление изменения вверх(1) или вниз(-1), только если это изменение больше либо равно 0,5 градуса (можно потом откорректировать эту величину), в противном случае, изменение на менее чем 0,5 градуса считать несущественным, а температуру стабильной (
direction=0)!
Код: Выделить всё
// Сравнение со средним значением с учетом разницы по модулю 0.5
if (abs($avg_t-$t)>=0.5) {
if ($t>$avg_t) {
$d=1;
} else {
$d=-1;
}}
else {
$d=0;
}
для примера весь мой код
tempChanged
Код: Выделить всё
$t=$this->getProperty("temp");
$this->setProperty("updated",time());
$this->setProperty("updatedTime",date("H:i",time()));
$this->setProperty("alive",1);
$ot=$this->object_title;
$alive_timeout=(int)$this->getProperty("aliveTimeOut");
if (!$alive_timeout) {
$alive_timeout=30*60; // 30 минут
}
clearTimeOut($ot."_alive");
setTimeOut($ot."_alive","sg('".$ot.".alive',0);",$alive_timeout);
$t=round($t,1);
if (($t > 80) || ($t < -50)) return;
// Получение среднего значения из истории
//Получить id свойства
$prop_id=$this->getPropertyByName('temp1', $this->class_id, $this->id);
//Получаем VALUE_ID для следующей таблицы
$pvalue=SQLSelectOne("SELECT * FROM pvalues WHERE PROPERTY_ID='".$prop_id."' AND OBJECT_ID='".$this->id."'");
//Получаем средние значения температуры за последние 30 минут
$start_time=time()-30*60; // 30 минут
$arr_t = SQLSelectOne("SELECT avg(VALUE) as AVG_V FROM phistory WHERE VALUE_ID='".$pvalue['ID']."' AND ADDED>='".date('Y-m-d H:i:s', $start_time)."'");
$avg_t=round($arr_t[AVG_V], 1);
// Историю храним именно в temp1
$this->setProperty('temp1',$t);
if ($params['uptime']) {
$this->setProperty('uptime',$params['uptime']);
}
// Сравнение со средним значением с учетом разницы по модулю 0.5
if (abs($avg_t-$t)>=0.5) {
if ($t>$avg_t) {
$d=1;
} else {
$d=-1;
}}
else {
$d=0;
}
$this->setProperty('direction',$d);
$linked_room=$this->getProperty("LinkedRoom");
if ($linked_room) {
setGlobal($linked_room.'.Temperature',$t);
}
теперь стало как мне надо (я так думаю):

- Скриншот 2014-12-02 00.41.08.png (254.51 КБ) 13215 просмотров