функция ggUpd("объект.свойство") возвращает массив. Со временем обновления свойства в кэше, конечно, проще, но у всех этого нету(
а там просто добавить поле UPDATED и по умолчанию поставить current timestamp. Тогда при записи автоматически там время изменения будет фиксироваться средствами mysql без кода php. При этом получение значения и времени вообще одним запросом получается безо всяких getObject & getPropertyByName
У меня была мысль завернуть код в функцию. Раньше я часто так делал. Но как то раз поделился примером тут, совсем забыв что там есть мои функции. Теперь стараюсь штатными средствами обходиться, или SQL в коде. Вообще конечно быстрее было бы смотреть на колонку `PROPERTY_NAME` таблицы `pvalues`, а если там нет, то искать уже по id. Но это всё уже ведет с созданию функции.
Вот пара примеров, где я использую время записи свойства:
Шаблон поведения. Ответ на вопрос "Какая температура на кухне"SPOILER_SHOW
/* Запускается из объектов класса Rooms для расчета средней температуры при её изменении
вычисляет среднюю температуру комнат для передачи её объекту термостата котла
*/
$check=array('Bedroom','HallArea','KitchenArea','Livingroom','OfficeRoom');
$t_avg=0; //средняя температура
$r_count=0; //количество принятых комнат
foreach($check as $r) {
$prop_id=getValueIdByName($r, 'Temperature');
$arr_s = SQLSelectOne("SELECT UNIX_TIMESTAMP(UPDATED) as UPDATED, VALUE FROM `pvalues` WHERE ID=$prop_id");
if (time()-$arr_s['UPDATED'] < 60*60*3) {
echo 'температура '.gg("$r.inRoomText").' '.$arr_s['VALUE'].'<br>';
$r_count++;
$t_avg=$t_avg+$arr_s['VALUE'];
} else {
echo 'данные о температуре '.gg("$r.inRoomText").' не актуальны <br>';
}
}
if (!$r_count) {
echo 'Данные не получены. Взять среднее по последним измерениям <br>';
foreach($check as $r) {
$r_count++;
$t_avg=$t_avg+gg("$r.Temperature");
}
}
$t_avg=round($t_avg/$r_count, 1);
echo "Средняя температура в доме $t_avg <br>";
// передать данные в объект термостата
sg('thrm_alpha.airCurrentTemp', $t_avg);
В ответе у меня сейчас следующее. Как раз батарейка села в одной комнате. Её температура в расчет не принимается.
температура в спальней комнате 26.4
температура в холле 25.7
температура на кухне 26
температура в гостиной комнате 26.8
данные о температуре в кабинете не актуальны
Средняя температура в доме 26.2
SELECT *
FROM pvalues
JOIN objects ON pvalues.OBJECT_ID = objects.id
JOIN properties ON pvalues.PROPERTY_ID = properties.id
WHERE pvalues.PROPERTY_NAME != CONCAT_WS( '.', objects.TITLE, properties.TITLE )
SQL2SPOILER_SHOW
SELECT *
FROM `pvalues`
WHERE `PROPERTY_NAME` <> CONCAT( (
SELECT title
FROM `objects`
WHERE pvalues.OBJECT_ID = objects.id
), '.', (
SELECT title
FROM `properties`
WHERE pvalues.PROPERTY_ID = properties.id
) )
в результате пусто, и это хорошо. Весьма давненько были тут трудности. У кого в этой колонке пусто, а у кого вообще левые имена. Получается теперь можно уверенно смотреть на эту колонку, а уж если не нашел, искать способом выше. Очень хороший вариант сделать функцию и предложить Pull Request. Ни разу такого не делал
Bagir писал(а): Пн авг 15, 2022 11:11 am
У меня была мысль завернуть код в функцию. Раньше я часто так делал. Но как то раз поделился примером тут, совсем забыв что там есть мои функции. Теперь стараюсь штатными средствами обходиться, или SQL в коде. Вообще конечно быстрее было бы смотреть на колонку `PROPERTY_NAME` таблицы `pvalues`, а если там нет, то искать уже по id. Но это всё уже ведет с созданию функции.
Вот пара примеров, где я использую время записи свойства:
Шаблон поведения. Ответ на вопрос "Какая температура на кухне"SPOILER_SHOW
/* Запускается из объектов класса Rooms для расчета средней температуры при её изменении
вычисляет среднюю температуру комнат для передачи её объекту термостата котла
*/
$check=array('Bedroom','HallArea','KitchenArea','Livingroom','OfficeRoom');
$t_avg=0; //средняя температура
$r_count=0; //количество принятых комнат
foreach($check as $r) {
$prop_id=getValueIdByName($r, 'Temperature');
$arr_s = SQLSelectOne("SELECT UNIX_TIMESTAMP(UPDATED) as UPDATED, VALUE FROM `pvalues` WHERE ID=$prop_id");
if (time()-$arr_s['UPDATED'] < 60*60*3) {
echo 'температура '.gg("$r.inRoomText").' '.$arr_s['VALUE'].'<br>';
$r_count++;
$t_avg=$t_avg+$arr_s['VALUE'];
} else {
echo 'данные о температуре '.gg("$r.inRoomText").' не актуальны <br>';
}
}
if (!$r_count) {
echo 'Данные не получены. Взять среднее по последним измерениям <br>';
foreach($check as $r) {
$r_count++;
$t_avg=$t_avg+gg("$r.Temperature");
}
}
$t_avg=round($t_avg/$r_count, 1);
echo "Средняя температура в доме $t_avg <br>";
// передать данные в объект термостата
sg('thrm_alpha.airCurrentTemp', $t_avg);
В ответе у меня сейчас следующее. Как раз батарейка села в одной комнате. Её температура в расчет не принимается.
температура в спальней комнате 26.4
температура в холле 25.7
температура на кухне 26
температура в гостиной комнате 26.8
данные о температуре в кабинете не актуальны
Средняя температура в доме 26.2
покажь время выпонение данных выше примеров, количество потребляемой памяти, количество запросов при выполнении
а потом сравни это с одним селектом без учета живости правда, но как часто батарейка садиться
ну и вопрос зачем такое городить и использовать часто когда батарейка раз в пару лет?!
а сам расчет не сильно критичен, средняя как показометр юзается и даже если один сенсор сдох, то последняя температура в среднем не сильно и повлияет на время замены батарейки!
а вообще среднюю считаешь по количеству комнат без учета из объема, т.е. это попугаи
Последний раз редактировалось Logrus Пн авг 15, 2022 12:16 pm, всего редактировалось 2 раза.
Telegram | Блог
Raspberry Pi3, с образа от Сергея 3.31, PHP 7, флешка 16 Гб работает с 10.09.2017
Почти всё время уходит на исправление ошибок, оставшееся - на их повторение. (с) ))) Спасибо
Bagir писал(а): Пн авг 15, 2022 11:29 am
Кстати сейчас выполнил у себя вот такой запрос
SQL1SPOILER_SHOW
SELECT *
FROM pvalues
JOIN objects ON pvalues.OBJECT_ID = objects.id
JOIN properties ON pvalues.PROPERTY_ID = properties.id
WHERE pvalues.PROPERTY_NAME != CONCAT_WS( '.', objects.TITLE, properties.TITLE )
SQL2SPOILER_SHOW
SELECT *
FROM `pvalues`
WHERE `PROPERTY_NAME` <> CONCAT( (
SELECT title
FROM `objects`
WHERE pvalues.OBJECT_ID = objects.id
), '.', (
SELECT title
FROM `properties`
WHERE pvalues.PROPERTY_ID = properties.id
) )
в результате пусто, и это хорошо. Весьма давненько были тут трудности. У кого в этой колонке пусто, а у кого вообще левые имена. Получается теперь можно уверенно смотреть на эту колонку, а уж если не нашел, искать способом выше. Очень хороший вариант сделать функцию и предложить Pull Request. Ни разу такого не делал
трудности тут (и такого еще полно в самом ядре мдм) приводили к куче проблем в целом
это поправили не так давно в сетглобал, но правильней писал выше при создании классового сразу у всех объектов создавать записи в пвалюес
Telegram | Блог
Raspberry Pi3, с образа от Сергея 3.31, PHP 7, флешка 16 Гб работает с 10.09.2017
Почти всё время уходит на исправление ошибок, оставшееся - на их повторение. (с) ))) Спасибо
Проблема ИМХО не в определении времени последнего изменения, а в контроле работоспособности устройств (длительное отсутствие показаний - один из признаков неисправности). В ПУ время изменения свойства пишется. Можно задавать максимальное время отсутствия получения данных. Это дополнительно нагружает систему, но для критически важных устройств такой подход обоснован.
Полазал в своем коде, где я использую время записанного свойства. А и правда много где. Так почему бы действительно не быть такой функции. Минусы затеи конечно есть. Люди смотрящие CONNECT не поймут код, хоть комментарии каждый раз оставляй. Впрочем, это тоже решение. Вот мой вариант. Написана в стиле функций файла objects.class.php
И ещё есть момент. Свое подобное добро я храню в файле .\lib\my.class.php Но если после обновлений одноименная функция появится, то всё ляжет. Поэтому в начале имени своей функции лучше добавить 'my'
$v= mygetGlobalWithUpd('KitchenArea.Temperature');
echo $v['VALUE'].' '.$v['UPDATED'];
/**
* Summary of mygetGlobalWithUpd
* @param mixed $varname Variable name
* @return array
*/
function mygetGlobalWithUpd($varname)
{
$tmp = explode('.', $varname);
if (isset($tmp[2])) {
$object_name = $tmp[0] . '.' . $tmp[1];
$varname = $tmp[2];
} elseif (isset($tmp[1])) {
$object_name = $tmp[0];
$varname = $tmp[1];
} else {
$object_name = 'ThisComputer';
}
/*
Получить значение из таблицы pvalues сразу по имени Объект.Свойство
*/
$sqlQuery = "SELECT UNIX_TIMESTAMP(UPDATED) as UPDATED, VALUE
FROM pvalues
WHERE PROPERTY_NAME = '" . DBSafe($object_name . '.' . $varname) . "'";
$value = SQLSelectOne($sqlQuery);
//$value='';
// Если получить не удалось
if (!isset($value['UPDATED'])) {
/*
Имена объектов находятся в таблице objects и они должны быть уникальными
Для начала нам нужно получить id нашего объекта и id класса которому принадлежит объект
*/
$sqlQuery = "SELECT ID, CLASS_ID
FROM objects
WHERE TITLE= '" . DBSafe($object_name) . "'";
$value = SQLSelectOne($sqlQuery);
$obj_id = $value['ID'];
$class_id = $value['CLASS_ID'];
if (!$obj_id) { return 0; }
/* Имена свойств находятся в таблице properties
с указанием id класса если свойство заданно на уровне класса,
или id объекта если свойство принадлежит объекту лично.
*/
$sqlQuery = "SELECT ID
FROM properties
WHERE TITLE= '" . DBSafe($varname) . "' AND (CLASS_ID='" . (int)$class_id . "' OR OBJECT_ID='" . (int)$obj_id . "')";
$value = SQLSelectOne($sqlQuery);
$prop_id = $value['ID'];
if (!$prop_id) { return 0; }
/*
значения свойств находятся в таблице pvalues
*/
$sqlQuery = "SELECT UNIX_TIMESTAMP(UPDATED) as UPDATED, VALUE
FROM pvalues
WHERE PROPERTY_ID = " . (int)$prop_id . " AND OBJECT_ID = " . (int)$obj_id;
$value = SQLSelectOne($sqlQuery);
//echo 'длинный путь ';
}
if (isset($value['UPDATED'])) {
return $value;
} else {
return 0;
}
}
AK1 писал(а): Пн авг 15, 2022 2:45 pm
Проблема ИМХО не в определении времени последнего изменения, а в контроле работоспособности устройств
Конечно, я для этого использую штатное свойство .alive
А для контроля у меня есть скрипт SearchProblemObjects. Вызывается из домашних страниц с параметром 1 чтобы сделать таблицу. И периодически по времени.
Все сделано хорошо. Значит надо организовать правильную реакцию на неисправное устройство (оповестить, исключить из подсчета средней температуры.....). Похожие проблемы. Последнее время стал задуваться газовый котел. Вывел в телеграм оповещение о снижении ниже критичного порога температуры котла.
AK1 писал(а): Пн авг 15, 2022 3:17 pm
Все сделано хорошо.
ты сейчас пошутил?
куча нафиг не нужных запросов, поллингом а не реакция по изменению свойства
ужасная реализация
Telegram | Блог
Raspberry Pi3, с образа от Сергея 3.31, PHP 7, флешка 16 Гб работает с 10.09.2017
Почти всё время уходит на исправление ошибок, оставшееся - на их повторение. (с) ))) Спасибо