Иващенко Тарас
г.Киев

 

Построил я загородный домик, поскольку в нем не живу, столкнулся с проблемой определения температуры. На стройке живет теща. Вода в систему отопления набрана. Опытным путем определено, что при +8 в доме, трубы на стенах за гипсокартоном начинают промерзать, а при +18 тёща болеть. Вот и возникла идея мониторить температуру удаленно.

После поисков в Интернете на поисковиках, было закуплено 2 девайса: отечественного производства USB-термометр MP707, позволяющий дистанционно через Интернет мониторить показания температуры, и китайский Софт termoHID.

 

Рис.1. Внешний вид цифрового USB-термометра MP707.

 

Софт к обоим прилагался. Китайское творчество было наляписто, но по функцианалу немного превосходило наше, но к нашему девайсу можна подключать до 10 датчиков DS18B20. Этот аргумент был решающим.

Сейчас в системе 4 датчика, улица, 1-й этаж, 2-й этаж и чердак. Накоплено год статистики.

Фронт выглядит вот так: посмотреть рисунок

 

ПО MP707 умеет записывать результаты измерений в текстовые файлы. Так что долго не думая на ASP был набросан преобразователь файлов в таблицы. Читать такие таблицы оказалось нелегко, а главное трудно заметить момент когда же все таки температура не в норме. Вот тут то пришли на помощь коллеги, и подтолкнули на правильную дорогу. В поле зрения попал javascript Highstock. Как им пользоватся расписано в статьях Highstock: мониторим Премию Рунета и Динамические графики на основе highstock.

После некоторого бдения таблицы на ASP были совмещены с JS. По сути графики получились такие же как и сейчас, но строились по файлам. Через два месяца работы от файлов пришлось отказаться. Обработка файлов длилась невероятно долго. Решение было принято молниеносно — читаем графики из MySQL. ПО MP707 позволяет периодично опрашивать датчики и после выполнять bat файлы. Был написан VBScript которй складирует результаты измерений в MySQL. В скрипте есть преобразование текстовой даты в дату в секундах с 1970, а также проверка на существование записи с таким временем.

 

Const ForReading = 1

Const TristateUseDefault = -2

Dim FSO

Set FSO = CreateObject("Scripting.FileSystemObject")

Dim FilePath

FilePath = "C:\BM1707\bm1707.temp"

set cn = CreateObject("ADODB.Connection")

cn.connectionstring = "Driver={MySQL ODBC 5.1 Driver};Server=localhost;DataBase=test; " &_

"USER=usr;PASSWORD=psw;"

cn.open

If FSO.FileExists(FilePath) Then

Dim file

Set file = FSO.GetFile(FilePath)

Dim TextFileStream

Set TextFileStream = file.OpenAsTextStream(ForReading,TristateUseDefault)

Do While Not TextFileStream.AtEndOfStream

Dim line

line = TextFileStream.ReadLine

curday = Mid(Line,2,2)

curmnth = Mid(Line,5,2)

curyear = Mid(Line,8,4)

curData = Mid(Line,2,10)

curhour = Mid(Line,13,2)

curmin = Mid(Line,16,2)

cursec = Mid(Line,19,2)

curdt = curyear & curmnth & curday & curhour & curmin & cursec

curhour = Cint(curhour)

curmin = Cint(curmin)

cursec = Cint(cursec)

aspdate = CDate(curData)

javadt = ((((aspdate - 25569) * 24 + curhour) * 60 + curmin) * 60 + cursec) * 1000

sqlStr = "SELECT Count( * ) FROM temperatures WHERE javadatetime = " & javadt

res = cn.execute(sqlStr)

if res(0)="0" then

line = trim(Mid(Line,24))

cnt = 1

lst = Split(line)

for each str in lst

nm = ""

val = ""

vals = Split(str,"=")

for each z in vals

if nm = "" then

nm = z

else

val = Replace(z,",",".")

end if

next

if (nm <> "") and (val <> "") then

cmdStr = "INSERT INTO temperatures" &_

"(measurementdatetime, thermometerid, value, javadatetime, thermometername)" &_

"VALUES ('" & curdt & "','" & cnt & "','" & val & "','" & javadt & "','" & nm & "')"

cn.execute cmdStr

End If

cnt = cnt + 1

next

End if

Loop

TextFileStream.Close

Set TextFileStream = Nothing

End If

cn.close

Дальше адаптер на PHP который формирует JSON для Highstock.

$rcn = mysql_connect("localhost","usr","psw");

mysql_select_db("test");

$termid = " and `thermometerid` = 2";

$last = "order by `measurementdatetime`";

$from = "";

$to = "";

$funk = "MIN";

if (isset($_GET['termid'])) $termid=" and `thermometerid` = ".$_GET['termid'];

if (isset($_GET['last'])) $last="order by `measurementdatetime` desc, 'termid'

limit ".$_GET['last'];

if (isset($_GET['from'])) $from=" and `measurementdatetime` >= ".$_GET['from'];

if (isset($_GET['to'])) $to=" and `measurementdatetime` <= ".$_GET['to'];

if (isset($_GET['funk'])) $funk="".$_GET['funk'];

$sqlstr = "SELECT MIN(`javadatetime`) as javadatetime, ROUND(".$funk."(`value`),1) as value

FROM `temperatures`

WHERE 1 ".$termid." ".$from." ".$to."

group by TO_DAYS(`measurementdatetime`)

".$last;

$res = mysql_query($sqlstr);

$number = mysql_num_rows($res);

printf("[");

$first = false;

if ($number > 0)

{

while ($row=mysql_fetch_array($res)) {

if ($first) printf(",");

printf("[");

printf($row['javadatetime']);

printf(", ");

printf($row['value']);

printf("]");

$first = true;

}

}

printf("]");

mysql_close();

Пример вывода графика:

var cnt = 0, seriesOptions = [], names = ['MAX','AVG', 'MIN'];

createAll();

function createAll() {

cnt = 0;

$.each(names, function(i, name) {

$.getJSON('http://tarasii.dyndns.org/minmax.php?termid=2&funk='+name, function(data) {

seriesOptions[i] = {name: name, data: data, tooltip: { yDecimals: 1}};

cnt++;

if (cnt == names.length) {

createChart();

}

});

});

}

function createChart() {

window.chart = new Highcharts.StockChart({

chart : { renderTo : 'container'}, title : { text : 'Day Temperature Statistics'},

xAxis : { maxZoom : 1 * 24 * 3600000 // fourteen days},

series : seriesOptions

});

}

Недавно опять же колеги натолкнули меня на jQuery gauge widget (спс ASM). Получились аналоговые термометры и часы

function createGauge(inGauge) {

inGauge.jqxLinearGauge({

orientation: 'vertical', width: 80, height: 150,

ticksMajor: { size: '10%', interval: 10 },

ticksMinor: { size: '5%', interval: 2.5, style: { 'stroke-width': 1, stroke: '#aaaaaa'} },

max: 40, min: -40,

pointer: { size: '5%' }, colorScheme: 'scheme05',

labels: {position: 'far', interval: 20, formatValue: function (value, position) {

if (value === -40) {

return '°C';

}

return value + '°';

}

},

animationDuration: 100

});

};

Скрипт который отправляет результаты на openweathermap

On Error Resume Next

set cn = CreateObject("ADODB.Connection")

cn.connectionstring = "Driver={MySQL ODBC 5.1 Driver};Server=localhost;DataBase=test; " &_

"USER=usr;PASSWORD=pwd;"

cn.open

sqlStr = "SELECT t.value as vl, transactiondatetime,thermometername FROM temperatures t where thermometername='Outdor' order by transactiondatetime desc limit 1; "

res = cn.execute(sqlStr)

str = FormatNumber(res(0),1,-1,0,0)

str = Replace(Str,",",".")

cn.close

Set cn = Nothing

strURL = "http://openweathermap.org/data/post"

strDatatoSend ="user=usr&password=pwd&temp="&str&"&lat=50.5193&long=30.5915&alt=100"

Dim objHTTP

Set objHTTP = CreateObject("Microsoft.XMLHTTP") 'Create XML HTTP object for the Post method

objHTTP.open "POST", strURL, False, "usr", "pwd" 'Opening the HTTP post method

objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"

objHTTP.send strDatatoSend 'Sending the request

Set objHTTP = Nothing

Пример гаджета для windows7 который показывает температуру со станции openweathermap

Чтение данных происходит скриптом jquery

function updateList() {

$.getJSON('http://openweathermap.org/data/2.1/weather/station/46933?type=json&callback=?', function(json) {

$.each(json, function(i, head) {

if(i=="main"){

curTmp = Math.round((head.temp-273)*10)/10;

if (curTmp>0){

$('#main').html('

+'+curTmp+'°C
');

}else{

$('#main').html('

-'+curTmp+'°C
');

}

}

});

});

}

 

Немного об оборудовании.

Контроллер MP707 соединен с датчиками DS18B20 витой парой, датчики подключены параллельно. Длина шины около 10 метров.

По началу сервером был нетбук ASUS Eee PC900H под управлением WIN XP.

Спустя некоторое время сервер переехал на материнку miniATX VIA C7-D 1800MHz в старом компьютерном AT-корпусе.
 

 

 

По стоимости компонентов, включая «сервер», можно уложится в 100 $.

 

 

Новинки

Вы недавно смотрели

              
Рейтинг@Mail.ru Яндекс.Метрика