Предыдущее значения свойства с историей

Использование системы в различных ситуациях, вопросы программирования сценариев.

Модератор: immortal

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

Предыдущее значения свойства с историей

Сообщение Bagir » Сб сен 20, 2014 12:02 am

Как получить? Вероятно SQL запросом. Это я мог бы, но никак не разберусь в структуре базы. Таблицу нашел. Должно быть это phistory. Но как узнать VALUE_ID? Нашел таблицу объектов и свойств. Нашел где записано количества дней истории. Но как узнать VALUE_ID так и не понял.
Помогите запросом, или инфой как получить VALUE_ID из таблицы phistory.
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
denis
Сообщения: 284
Зарегистрирован: Сб ноя 24, 2012 11:47 am
Благодарил (а): 32 раза
Поблагодарили: 28 раз

Re: Предыдущее значения свойства с историей

Сообщение denis » Сб сен 20, 2014 7:33 am

За это сообщение автора denis поблагодарил:
Bagir (Сб сен 20, 2014 9:57 am)
Рейтинг: 1.16%
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 375 раз

Re: Предыдущее значения свойства с историей

Сообщение Bagir » Сб сен 20, 2014 9:57 am

Вот спасибо! Как только не пробовал искать, ничего не попадалось. И надо было же попробовать по "FROM phistory WHERE" Ну как сам не догадался... Можно получить не только последнее значение, но еще и анализировать изменения данных. Отличный пример!
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 375 раз

Re: Предыдущее значения свойства с историей

Сообщение Bagir » Сб сен 20, 2014 11:48 am

Сделал так:
Метод 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);
} 
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Vit
Сообщения: 867
Зарегистрирован: Вт янв 17, 2012 12:31 pm
Благодарил (а): 121 раз
Поблагодарили: 78 раз

Re: Предыдущее значения свойства с историей

Сообщение Vit » Сб сен 20, 2014 12:04 pm

Bagir писал(а): Теперь у датчиков температуры на сценах есть треугольник, показывающий направление изменения температуры. Вот как то так:
Изображение
Как значек изменения ниже датчика расположил?
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 375 раз

Re: Предыдущее значения свойства с историей

Сообщение Bagir » Сб сен 20, 2014 12:20 pm

Можно позиционировать с помощью CSS. Я там порядочно поднабрался, пока трубы рисовал, но тут я просто перед тегом, который рисует значок, поставил <br>
За это сообщение автора Bagir поблагодарил:
Vit (Сб сен 20, 2014 12:25 pm)
Рейтинг: 1.16%
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Bagir
Сообщения: 1615
Зарегистрирован: Вт сен 17, 2013 6:46 pm
Откуда: Ярославская область город Углич
Благодарил (а): 212 раз
Поблагодарили: 375 раз

Re: Предыдущее значения свойства с историей

Сообщение Bagir » Вт сен 23, 2014 12:22 am

Я уже приводил пример кода метода 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 опять обрело смысл. Незначительные колебания температуры - это не повод показывать стрелку изменения.
Полный код метода tempChangedПоказать

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

// $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);
} 
Windows 10, HTTP, MegaD, Z-Wave, 1-Wire, CONNECT
Аватара пользователя
Vovix
Сообщения: 1155
Зарегистрирован: Пн янв 27, 2014 1:43 am
Откуда: г.Ижевск
Благодарил (а): 60 раз
Поблагодарили: 532 раза
Контактная информация:

Re: Предыдущее значения свойства с историей

Сообщение Vovix » Чт ноя 27, 2014 11:17 pm

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 опять обрело смысл. Незначительные колебания температуры - это не повод показывать стрелку изменения.
Полный код метода tempChangedПоказать

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

// $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


изменил код в двух местах:

в самом начале добавил

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

$t=$this->getProperty("temp");
и заменил

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

$t=round($params['t'], 1);
на

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

$t=round($t,1);
и всё стало работать правильно!

видимо у вас метод вызывается с параметром при изменении, а у меня без входящего параметра...
наверно так!
Мой -CONNECT-
Windows 7(PHP 7.2) + Raspberry Pi(освещение на 1-Wire) + MP751(управление) + ESP8266(сенсоры) + LAN(сенсоры)
-=: Если вам помогло моё сообщение, нажмите кнопку "Поблагодарить за сообщение автора: Vovix" (кнопка Спасибо) справа! :=-
Аватара пользователя
Vovix
Сообщения: 1155
Зарегистрирован: Пн янв 27, 2014 1:43 am
Откуда: г.Ижевск
Благодарил (а): 60 раз
Поблагодарили: 532 раза
Контактная информация:

Re: Предыдущее значения свойства с историей

Сообщение Vovix » Вс ноя 30, 2014 1:44 am

И еще, мне градиентная заливка была не нужна, а вот direction хотел прикрутить!

Вот я так сделал без использования дополнительных состояний, прямо в коде самого значения температуры:

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

<span style="font-size:42px;font-weight:bold; 
background: url(/images/%TempSensor1.direction%.gif) bottom 10px left / 20px 20px no-repeat;">
&nbsp;&nbsp;%TempSensor1.temp1%°C</span>
Вложения
Скриншот 2014-11-30 02.40.47.png
Скриншот 2014-11-30 02.40.47.png (24.76 КБ) 13256 просмотров
Мой -CONNECT-
Windows 7(PHP 7.2) + Raspberry Pi(освещение на 1-Wire) + MP751(управление) + ESP8266(сенсоры) + LAN(сенсоры)
-=: Если вам помогло моё сообщение, нажмите кнопку "Поблагодарить за сообщение автора: Vovix" (кнопка Спасибо) справа! :=-
Аватара пользователя
Vovix
Сообщения: 1155
Зарегистрирован: Пн янв 27, 2014 1:43 am
Откуда: г.Ижевск
Благодарил (а): 60 раз
Поблагодарили: 532 раза
Контактная информация:

Re: Предыдущее значения свойства с историей

Сообщение Vovix » Пн дек 01, 2014 11:37 pm

Еще подумал я: очень редко я вижу, что направление изменения равно 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
Скриншот 2014-12-02 00.41.08.png (254.51 КБ) 13206 просмотров
Мой -CONNECT-
Windows 7(PHP 7.2) + Raspberry Pi(освещение на 1-Wire) + MP751(управление) + ESP8266(сенсоры) + LAN(сенсоры)
-=: Если вам помогло моё сообщение, нажмите кнопку "Поблагодарить за сообщение автора: Vovix" (кнопка Спасибо) справа! :=-
Ответить