[фото счетчиков воды]
В один прекрасный день мне захотелось поэкспериментировать с данными получаемыми с счетчиков, взяв тестер и установив в режим подачи звукового сигнала при замыкании начал щупать контакты, в результате получилось что контакт разомкнут и замкнут определенное количество проходящих через счетчик литров воды. Получаем импульсы, пока контакт замкнут, то есть логическая единица показания на механическом счетчике показывают от 0 до 7 литров, пока разомкнут, то есть логический ноль то счетчик показывает от 7 до 0 литров, результат импульсы по 3 и 7 литров, тут все понятно, идем дальше.
Теперь нам нужно как то снять эти наши импульсы с помощью компьютера, самый простой способ без паяльника это LPT порт. Как видно на картинке ниже, LPT порт имеет 25 контактов и три регистра, в итоге мы получаем:
8 двунаправленных контактов (регистр Data) - данные туда может записать и программа и внешнее устройство
5 однонаправленных контактов (регистр Status) - данные туда может записать только внешнее устройство
4 однонаправленных контакта (регистр Control) - данные туда может записать только программа
[картинка LPT порта]
Так как мы будем только снимать показаниям нам понадобится регистр Status, а точнее 2 из 4 его контактов. Но стоит учесть что на контактах этого регистра находится +5 вольт, то есть логическая единица, если соединить контакт с землей то на нем будет логический ноль, а значит контакты этого регистра инвертированы. И так если мы соединим один провод нашего счетчика с вывод земли LPT порта, а другой с выводом Status, то при протекании жидкости через счетчик наш LPT порт будет видеть снимать импульсы.
LPT порт в моем случае находится с сервере под Linux, и снимать показания с lpt порта можно разными методами, я выбрал написании программы на СИ, ходя в СИ я не силен, код представлен ниже:
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
#define BASEPORT 0x379
int dec2bin(int p)
{
int a,b,c=1,d=0;
while (p!=0)
{
a = p%2;
b = a * c;
d = d + b;
p = p/2;
c = c * 10;
}
return d;
}
int main()
{
if (ioperm(BASEPORT, 3, 1)) {perror("ioperm"); exit(1);}
printf("%d\n", dec2bin(inb(BASEPORT)));
if (ioperm(BASEPORT, 3, 0)) {perror("ioperm"); exit(1);}
exit(0);
}
Код: Выделить всё
gcc lpt.c -o lpt
Теперь нам нужно привести получаемые данные в человеческий вид, для это нам понадобится мой любимый php. Для вычисления показаний счетчика я использовал программу на php и базу mysql. Ниже смотри код:
Код: Выделить всё
<?php
$stop_server = false;
$last_cold = 0;
$last_hot = 0;
$mysql_server = "localhost";
$mysql_user = "root";
$mysql_password = "";
$mysql_db = "test"
$conn = mysql_connect($mysql_server, $mysql_user, $mysql_password);
$db = mysql_select_db($mysql_db, $conn);
$sql = mysql_query("SELECT * FROM `param`", $conn);
for($i=0; $i < mysql_num_rows($sql); $i++)
{
$data = mysql_fetch_assoc($sql);
if($data['param_type'] == 'cold_water')
{
$cold_count = $data['param_value'];
}
if($data['param_type'] == 'hot_water')
{
$hot_count = $data['param_value'];
}
}
while(!$stop_server)
{
$result = shell_exec("lpt");
$cold = substr($result, 2, -6);
$hot = substr($result, 3, -5);
$timestamp = date("YmdHis");
if(!$conn)
{
$conn = mysql_connect($mysql_server, $mysql_user, $mysql_password);
$db = mysql_select_db($mysql_db, $conn);
}
if($last_cold != $cold){
$cold_read = true;
}else{
$cold_read = false;
}
if($cold == 1 AND $cold_read == true)
{
$last_cold = $cold;
$cold_count += 7;
mysql_query("UPDATE `param` SET `param_date`='".$timestamp."', `param_value`=".$cold_count." WHERE `param_type`='cold_water'", $conn);
$cold_read == false;
}
if($cold == 0 AND $cold_read == true)
{
$last_cold = $cold;
$cold_count += 3;
mysql_query("UPDATE `param` SET `param_date`='".$timestamp."', `param_value`=".$cold_count." WHERE `param_type`='cold_water'", $conn);
$cold_read == false;
}
if($last_hot != $hot){
$hot_read = true;
}else{
$hot_read = false;
}
if($hot == 1 AND $hot_read == true)
{
$last_hot = $hot;
$hot_count += 7;
mysql_query("UPDATE `param` SET `param_date`='".$timestamp."', `param_value`=".$hot_count." WHERE `param_type`='hot_water'", $conn);
$hot_read == false;
}
if($hot == 0 AND $hot_read == true)
{
$last_hot = $hot;
$hot_count += 3;
mysql_query("UPDATE `param` SET `param_date`='".$timestamp."', `param_value`=".$hot_count." WHERE `param_type`='hot_water'", $conn);
$hot_read == false;
}
echo "Cold Water: ".$cold_count." / Hot Water: ".$hot_count."\n";
sleep(5);
}
?>
Перед тем как запустить нашу программу, берем бумагу и карандаш и идем в туалет или туда где у вас стоит счетчик или несколько счетчиков (в моем случае это два счетчика холодная и горячая вода) и записываем показания на бумагу, возвращаемся и добавляем данные в базу данных, а именно таблицу param. Главное для холодной воды укажите param_type равный cold_water, а горячей hot_water и заполните соответствующие param_value только что снятыми показаниями со счетчика.
[картинка таблицы]
Теперь чтобы запустить нашу программу заходим в консоль, и пишем:
Код: Выделить всё
cd /etc/water/ && screen -AdmS water_count php -q water.php
Код: Выделить всё
screen -r water_count
[картинка консоли с запуском программы]
Теперь когда льем водичку наша программа считает сколько мы вылили, и можно не лазить за трубы, а удобно наблюдать все на компьютере. Но есть маленькая проблема, если повиснет компьютер или рубанут электричество, а у вас нету UPS тогда показания будут неверным, что же теперь делать? У меня нету UPS и поэтому после такой проблемы я иду в туалет переписываю текущие данные и обновляю их в БД и запускаю программу заново, конечно это не удобно, но бывает очень редко, раз или два за полгода, но так как у нас кустарный метод без паяльника иначе ни как.
Все классно, все работает, но все равно не счастлив, а почему? Потому что мне неудобно лазить постоянно в БД и смотреть показания, что делать? Все просто, пишем свой гаджет для Windows 7 для отображения данных в реальном времени. Прежде чем приступить к этому хочу рассказать почему все это делаю, во первых есть такой сайт http://www.gu-is.ru, куда ежемесячно я скидываю информацию по счетчикам куда удобнее чем звонить туда, почти никогда не мог дозвониться им, и решил отправлять данные со счетчиков автоматически через сайт, именно для этого я все это делаю, ну и конечно удобно наблюдать за показаниями воды прямо на рабочем столе.
[картинка рабочего стола с гаджетом]
Я не буду описывать в этой статье процесс создания гаджета, он прикреплен к статье, я лишь опишу принцип работы и что потребуется для этого. Первое что потребуется это веб сервер на котором будут лежать два файла, запросив которые будут выводить показания горячей и холодной воды, в свою очередь подключившись к нашему mysql серверу и посмотрев там. Файлы также прикреплены к статье и называются hot_water.php и cold_water.php, разместить вы их можете где угодно, главное чтобы они были доступны тем машинам на которых будет стоять гаджет.
И так прежде чем установить гаджет нужно изменить в нем пару строк в файле water.html, заменив там ссылки к файлам на ваши текущие, ищем две эти строки:
Код: Выделить всё
req.open('POST', 'http://192.168.1.10/water/hot_water.php', true);
req.open('POST', 'http://192.168.1.10/water/cold_water.php', true);
Теперь жмем правой кнопкой по рабочему столу, затем гаджеты и выбираем наш "Счетчик Воды" и перетаскиваем в удобное для вас место на рабочем столе, теперь гаджет будет снимать данные каждые 30 секунд, их вы также можете исправить в файле water.html вашего гаджета
[картинка с выбором гаджета и рабочий стол]
Выкладываю статью сперва сюда, жду вышей похвалы и конструктивной критики, пожеланий и предложений. AlexCo
Архив с данными к статье пока что не прикрепляю, по первой просьбе скомпоную и выложу.