Webserver (Arduino+W5100). Примеры интеграции с MajorDoMo.

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

Модератор: immortal

electric
Сообщения: 309
Зарегистрирован: Вт сен 17, 2013 10:11 pm
Благодарил (а): 3 раза
Поблагодарили: 56 раз

Webserver (Arduino+W5100). Примеры интеграции с MajorDoMo.

Сообщение electric » Вс янв 26, 2014 2:54 pm

Всем привет.
Давно наблюдаю за этим проектом, недавно решил таки влиться.
С точки зрения домашней автоматизации считаю для себя идеальной связку:
  • Центральный сервер с Linux Debian и MajorDoMo. Пока запущен на Raspberry Pi.
    Вариант конечно не идеальный - заметно как притормаживает, да и флешка под MySQL быстро помрет.
    В будущем думаю пересесть на cubieboard - он помощнее, тем более есть возможность подключить HDD через SATA.
  • На уровне ниже планирую применить связку Arduino+W5100, пока для опытов это Arduino Uno R3 и Arduino Ethernet Shield.
    В будущем можно применить Arduino Mega 2560 для увеличения кол-ва входов-выходов.
    Либо для компактности Arduino Nano с неофициальным шилдом ENC28J60.
Передача данных через HTTP поверх TCP. MDM будет запрашивать у Ардуины как веб-клиент данные аналоговых датчиков типа DS18B20, DHT22, BMP085 и прочих. Таким же образом будут передаваться команды на вкл/выкл дискретных выходов Ардуины.
Состояние дискретных входов Ардуина будет передавать в MDM как клиент при изменении их состояния.

Почему на напрямую на GPIO, а через Ардуину? Просто планирую ардуину сделать т.н. умным датчиком (исполнительным механизмом), к тому же на нее можно переложить часть вычислений/преобразований/проверок и пр., тем самым немного разгрузить малину.
На данный момент пробовал подключать через USB, работа связки MR3020 на OpenWRT и Arduino Nano через виртуальный com-порт в OpenWRT мне не понравилась. Как минимум раз в месяц стопорится обмен данными, иногда данные приходят "битыми". Пробовал все - и питание более надежное и различные программные заплатки и костыли, и различные преобразователи интерфейса (PL2303, FTDI232, CP102), все равно система не надежна. Да и не просто так в промышленной автоматики USB редко используется для работы 365/12/7/24... HTTP после всех этих заморочек мне показался просто детской сказкой)) Хотя может пока нет статистики такой, чтобы усомниться в этом...

Пример №1.1. Раз в минуту система с MajorDoMo (в качестве клиента) запрашивает у WEB-сервера (Arduino Uno R3 + Ethernet Shield W5100) температуру (датчики DS18B20).
Используется библиотека WebServer.h Webduino (https://github.com/sirleech/Webduino)

Итак, начнем снизу - Arduino Uno R3 + Arduino Ethernet Shield. К входу №2 ардуины подключены по 1-wire c подтяжкой через резистор 4,7К 3 датчика DS18B20. Для удобства работы с датчиками я заранее прочитал их адреса скетчем из примеров среды IDE. В моем случае:
  • Т1 - 284AEB340500007D
  • Т2 - 28459634050000D8
  • Т3 - 280F7234050000A7
Использую библиотеку Webduino, она довольно объемная и её функционал избыточен для данного примера, но в будущем планирую добавить некоторые команды и возможность Ардуины передавать данные в MDM как клиент.
Прошу прощения за быдло-код, я не программист, писал не сам. Куски кода взяты из различных источников, в т.ч. с этого форума.
Код Ардуины:

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

/**
* Контроллер-исполнительное устройство (к проекту http://smartliving.ru/)
* Platform: Arduino UNO R3 + EthernetShield W5100
* IDE: Arduino 1.0.5-r2
*
* обращение по http://xx.xx.xx.xx/ выдаст справочную информацию по этому устройству (нужно для того, чтобы когда обращаешься
* по IP к устройству понять что это за контроллер и пр.)
*
* обращение по http://xx.xx.xx.xx/sensors - вывод значений всех аналоговых датчиков DS18B20
* формат вывода:T1=xx,xx&T2=xx,xx&T3=xx,xx для удобства потом в php распарсить.
**/
#include <Ethernet.h>
#include <SPI.h>
#include "WebServer.h" // Webduino (https://github.com/sirleech/Webduino)
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE4, 0xDE, 0x35 }; // MAC-адрес нашего устройства
byte ip[] = { 192, 168, 69, 52 };
byte subnet[] = { 255, 255, 255, 0 };

#define VERSION_STRING "0.1"
#define COMPILE_DATE_STRING "2014-01-23"

#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress T1 = { 0x28, 0x4A, 0xEB, 0x34, 0x05, 0x00, 0x00, 0x7D };
DeviceAddress T2 = { 0x28, 0x45, 0x96, 0x34, 0x05, 0x00, 0x00, 0xD8 };
DeviceAddress T3 = { 0x28, 0x0F, 0x72, 0x34, 0x05, 0x00, 0x00, 0xA7 };

P(Page_info) = "<html><head><title>smartliving.ru controller " VERSION_STRING "</title></head><body>\n";
P(location_info) = "underground server room";
P(pin_info) = "D2 - 1-wire (many DS18S20)";
P(version_info) = VERSION_STRING ". Compile date: " COMPILE_DATE_STRING;

#define PREFIX ""
WebServer webserver(PREFIX, 80);
/**********************************************************************************************************************/
//Генерация и вывод информации об устройстве
void infoRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  server.printP(Page_info);
  server.print("IP:");
  server.print(Ethernet.localIP());
  server.print("<br>Location:");
  server.printP(location_info);
  server.print("<hr>Pin info:<br>");
  server.printP(pin_info);
  server.print("<hr>Pin current state: ");
  server.print("<hr><a href='/getdev'>1-wire devices</a>");
  server.print("<hr>Commands:<br>");
  server.print("<hr><br>Version info: ");
  server.printP(version_info);
}
//Вывод значений всех сенсоров. Парсинг в коде php клиента - в MDM.
void getSensors(WebServer &server, WebServer::ConnectionType type, char *, bool)
{
  server.httpSuccess();
  sensors.requestTemperatures();
  float t1 = sensors.getTempC(T1);
  float t2 = sensors.getTempC(T2);
  float t3 = sensors.getTempC(T3);
  if (isnan(t1) || isnan(t2) || isnan(t3)) {
    server.print("NOT FOUND");
  } else {
    server.print("T1=");
    server.print(t1);
    server.print("&T2=");
    server.print(t2);
    server.print("&T3=");
    server.print(t3);
    Serial.print("T1=");
    Serial.print(t1);
    Serial.print("&T2=");
    Serial.print(t2);
    Serial.print("&T3=");
    Serial.println(t3);
  }
}
/**********************************************************************************************************************/
void setup() {
  Serial.begin(9600);
  Serial.println("Start");
  sensors.begin();
  sensors.setResolution(T1, 12);
  sensors.setResolution(T2, 12);
  sensors.setResolution(T3, 12);
  
  Ethernet.begin(mac, ip, subnet); // Инициализируем Ethernet Shield

  webserver.setDefaultCommand(&infoRequest); // дефолтная страница вывода (информация о контроллере)
  webserver.addCommand("sensors", &getSensors); // отправка строки с результатами измерения
  webserver.begin();
  
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}
/**********************************************************************************************************************/
void loop() {
  char buff[64];
  int len = 64;
  webserver.processConnection(buff, &len); // process incoming connections one at a time forever
}
Через веб-браузер по ссылке "http://ip-адрес" выдается что то типа информационной странички. По ссылке "http://ip-адрес/sensors" выдается строка типа "T1=30.12&T2=28.75&T3=28.62".
Если у вас все так, то переходим далее.

Сверху у нас MDM, тут надо отправить запрос на сервер-Ардуину в виде "http://ip-адрес/sensors", считать строчку значений, затем её можно "распарсить" в php функцией parse_str($строка);. Есть несколько вариантов сделать запрос на php из MajorDoMo: wget, curl, socket, но я воспользовался file_get_contents, он самый простой мне показался... Правда надо будет его настроить - добавить тайм-аут хотя бы, пока не читал как это сделать. Итак, переходим в панель управления MDM -> Объекты, создаем там новый класс "tempSensors"
Изображение
Добавляем классу tempSensors свойства: direction, temp, updated и updatedTime.
Изображение
Так же на вкладке "методы" добавляем метод "tempChanged", используем "Выполнить код" и вставляем следующий текст:

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

//$params['t']
$old_temp=$this->getProperty('temp');
$t=round($params['t']*2)/2;
$this->setProperty('temp',$t);
if ($t>$old_temp) {
 $d=1;
} elseif ($t<$old_temp) {
 $d=-1;
} else {
 $d=0;
}
$this->setProperty('direction',$d);
$this->setProperty("updated",time());
$this->setProperty("updatedTime",date("H:i",time()));
Изображение
Теперь можно создавать наши объекты - температуры. Переходим на вкладку "Объекты" и создадим 3 объекта: "sensorT1", "sensorT2" и "sensorT3".
Изображение
Итак. Теперь нам надо в определенное время, например раз в минуту, записывать значения в "tempSensors.sensorT1" запуская метод "tempSensors.tempChanged".
Для этого создадим сценарий, нажимаем в меню слева "Сценарии", добавим новый сценарий с названием, например, " read_ds18b20", для реализации выбираем "php".
Вводим следующий текст:

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

$read = file_get_contents('http://192.168.69.52/sensors');
if ($read)
{
	parse_str($read);
}

if ($T1<>"" and $T1<>0 and $T1<>127 and $T1<>-127)
{
$T1 = round($T1,1);
callMethod('sensorT1.tempChanged',array('t'=>$T1));
}
if ($T2<>"" and $T2<>0 and $T2<>127 and $T2<>-127)
{
$T2 = round($T2,1);
callMethod('sensorT2.tempChanged',array('t'=>$T2));
}
if ($T3<>"" and $T3<>0 and $T3<>127 and $T3<>-127)
{
$T3 = round($T3,1);
callMethod('sensorT3.tempChanged',array('t'=>$T3));
Изображение
Так, нам осталось теперь раз в минуту выполнять этот скрипт. Вызов сделать очень просто, достаточно в "Объектах" найти класс "Timer", объект "ClockChime", в нем метод "onNewMinute".
Там уже есть некоторый текст, просто в конце добавляем строчку RunScript('read_ds18b20');
Изображение

Вот собственно и все. Можно добавить табличку в меню, чтобы отображались данные.
Далее будет описание небольшой проблемы, с которой я столкнулся, пока не разобрался...
Последний раз редактировалось electric Чт янв 30, 2014 11:08 pm, всего редактировалось 6 раз.
За это сообщение автора electric поблагодарили (всего 4):
annton (Вс окт 12, 2014 9:20 pm) • foxvlad (Пт янв 09, 2015 8:12 pm) • kawkay (Ср июл 15, 2015 9:10 am) • black label (Сб окт 29, 2016 6:06 pm)
Рейтинг: 4.65%
Было: Majordomo v.0.6.0.b на Cubietruck. OS Armbian с переносом на HDD
Стало: ioBroker на Cubietruck OS Armbian + ZigBee Xiaomi + OWFS + BLE.
electric
Сообщения: 309
Зарегистрирован: Вт сен 17, 2013 10:11 pm
Благодарил (а): 3 раза
Поблагодарили: 56 раз

Re: Webserver (Arduino+W5100). Опрос по инициативе MajorDoMo

Сообщение electric » Вс янв 26, 2014 3:10 pm

Точнее это не сколько проблема, а небольшой недочет.
Посмотрел я таблицу через phpMyAdmin, в которую пишутся переменные Т1, Т2, Т3 и их сопровождающие свойства.
Почему то у меня в таблицу заносятся по два значения, прямо друг за другом...
Вот скрин:
Изображение
Может наши гуру PHP посмотрят мой пример, найдут ошибку?
Заранее спасибо!

UPDATE:
Нашел ошибку...
Вот скрипт "read_DS18B20" что был с пояснениями ошибки:

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

$read = file_get_contents('http://192.168.69.52/sensors');
if ($read)
{
   parse_str($read);
}

if ($T1<>"" and $T1<>0 and $T1<>127)
{
$T1 = round($T1,1);
sg("sensorT1.temp", $T1); // Присваиваю значение, а затем...
callMethod('sensorT1.tempChanged',array('t'=>$T1)); // еще раз передаю через метод. Думаю достаточно передавать через метод.
}
if ($T2<>"" and $T2<>0 and $T2<>127)
{
$T2 = round($T2,1);
sg("sensorT2.temp", $T2); // Присваиваю значение, а затем...
callMethod('sensorT2.tempChanged',array('t'=>$T2)); // еще раз передаю через метод. Думаю достаточно передавать через метод.
}
if ($T3<>"" and $T3<>0 and $T3<>127)
{
$T3 = round($T3,1);
sg("sensorT3.temp", $T3); // Присваиваю значение, а затем...
callMethod('sensorT3.tempChanged',array('t'=>$T3)); // еще раз передаю через метод. Думаю достаточно передавать через метод.
Обновил в шапке, теперь все правильно.
Последний раз редактировалось electric Вс янв 26, 2014 7:24 pm, всего редактировалось 1 раз.
Было: Majordomo v.0.6.0.b на Cubietruck. OS Armbian с переносом на HDD
Стало: ioBroker на Cubietruck OS Armbian + ZigBee Xiaomi + OWFS + BLE.
vtec
Сообщения: 54
Зарегистрирован: Пн янв 20, 2014 7:35 pm
Благодарил (а): 0
Поблагодарили: 0

Re: Webserver (Arduino+W5100). Опрос по инициативе MajorDoMo

Сообщение vtec » Вс янв 26, 2014 6:29 pm

Зачем вам считывать температуру каждую минуту, я считаю это лишняя информация. Раз чем в 5 минут больше чем достаточно.
За 1 минуту температура воздуха навряд ли поменяется.
electric
Сообщения: 309
Зарегистрирован: Вт сен 17, 2013 10:11 pm
Благодарил (а): 3 раза
Поблагодарили: 56 раз

Re: Webserver (Arduino+W5100). Опрос по инициативе MajorDoMo

Сообщение electric » Вс янв 26, 2014 6:45 pm

vtec писал(а):Зачем вам считывать температуру каждую минуту, я считаю это лишняя информация. Раз чем в 5 минут больше чем достаточно.
За 1 минуту температура воздуха навряд ли поменяется.
Так 1 минута для примера (точнее для стресс-теста)...
Можно добавить в код метода ClockChime.onNewMinute конструкцию типа:

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

if (($m==10) || ($m==20) || ($m==30) || ($m==40) || ($m==50)) {
runScript('read_ds18b20');
}
Будет раз в 10минут выполняться... Соответственно по этому образцу можно любой интервал придумать...
Было: Majordomo v.0.6.0.b на Cubietruck. OS Armbian с переносом на HDD
Стало: ioBroker на Cubietruck OS Armbian + ZigBee Xiaomi + OWFS + BLE.
dmw
Сообщения: 469
Зарегистрирован: Вт мар 12, 2013 1:22 am
Благодарил (а): 41 раз
Поблагодарили: 81 раз

Re: Webserver (Arduino+W5100). Опрос по инициативе MajorDoMo

Сообщение dmw » Вс янв 26, 2014 7:26 pm

Код:

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

if (($m==10) || ($m==20) || ($m==30) || ($m==40) || ($m==50)) {
runScript('read_ds18b20');
}
Можно заменить на:

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

if (!($m%10)) {
runScript('read_ds18b20');
}
electric
Сообщения: 309
Зарегистрирован: Вт сен 17, 2013 10:11 pm
Благодарил (а): 3 раза
Поблагодарили: 56 раз

Re: Webserver (Arduino+W5100). Примеры интеграции с MajorDoM

Сообщение electric » Чт янв 30, 2014 11:18 pm

Мне не очень нравится код контроллера Arduino, что приведен в Примере 1.1, в шапке темы.
Дело в том, что библиотека "WebServer.h" Webduino слишком избыточна для этого примера...
Отъедает солидный кусок памяти контроллера.
Пробую изменить код, чтобы он занимал поменьше памяти в контроллере.
З.Ы. К слову,стандартные библиотеки SPI.h и Ethernet.h, так же весят не мало.
Чтобы написать действительно что то более мультисервисное - и управление реле, и отправку показаний датчиков, и срабатывание дискретных сигналов плюс математическая
обработка всего этого хозяйства, думаю надо переселиться на Мегу 2560.
Было: Majordomo v.0.6.0.b на Cubietruck. OS Armbian с переносом на HDD
Стало: ioBroker на Cubietruck OS Armbian + ZigBee Xiaomi + OWFS + BLE.
azh122
Сообщения: 113
Зарегистрирован: Вт янв 28, 2014 5:33 pm
Благодарил (а): 1 раз
Поблагодарили: 6 раз

Re: Webserver (Arduino+W5100). Примеры интеграции с MajorDoM

Сообщение azh122 » Пт янв 31, 2014 12:01 am

А что за проблема в работе связки MR3020 на OpenWRT и Arduino ??? Просто напрягли этим заявлением.
У меня фик знает уже который месяц без сбоев работает MR3020 в качестве мини веб сервера, а к нему уже с десяток простых и не очень мк подключено - кучка msp430, плюс Mega и ti stellarius. UART вытащил из роутера и все это хозяйство под модбасу подключил (на max485 еще разорился).
Щас решил объеденить все этим проектом (а то у меня еще одна сетка - в ввиде смарт розеток и выключателей - то же без сбоев. Причем не месяцы, а почти два года), плюс интелекта и статистики добавить.... Типа не стоит?
electric
Сообщения: 309
Зарегистрирован: Вт сен 17, 2013 10:11 pm
Благодарил (а): 3 раза
Поблагодарили: 56 раз

Re: Webserver (Arduino+W5100). Примеры интеграции с MajorDoM

Сообщение electric » Пт янв 31, 2014 8:57 am

azh122 писал(а):А что за проблема в работе связки MR3020 на OpenWRT и Arduino ??? Просто напрягли этим заявлением.
В своем сообщении я кратко описал чем недоволен.
У меня частенько в OpenWRT отваливается виртуальный com-порт, ну как часто - примерно раз в месяц.
Связка на данный момент работает так: К Ардуине подключены 4хDS18B20, 1xDHT22, 1xBMP085. Ардуина ждет по виртуальному UART (ttyUSB0 который) символ.
Соответственно роутер через cron раз в 5 мин запускает скрипт php, который отправляет в виртуальный UART некоторый символ и читает ответ типа "Т1=-25,8&Т2=-10,5&Т3=60,2&Т4=62,6&T5=25,5&H=48&P=772" Затем парсит его и записывает в БД SQLite. Второй скрипт стартует через каждые 10мин со сдвигом 2ми, т.е. 02, 12, 22 и т.д. и отправляет данные на narodmon.ru.
Чо за глюк с виртуальным UART - хз, разбираться неохото, тем более принял решение по приезду Кубика3 переселиться на MDM+Arduino (UNO/MEGA2560) в качестве WEB-сервера, передача данных и управление по http. Сейчас тестирую различные варианты на Малине и Arduino UNO+W5100. Малина все таки слабовата...
azh122 писал(а):У меня фик знает уже который месяц без сбоев работает MR3020 в качестве мини веб сервера, а к нему уже с десяток простых и не очень мк подключено - кучка msp430, плюс Mega и ti stellarius. UART вытащил из роутера и все это хозяйство под модбасу подключил (на max485 еще разорился).
Я рад, что у вас все работает бесперебойно)) С Модбасом не хочу связываться, считаю ИМХО серьезным минусом, что в сети может проявлять инициативу только мастер - т.е. в вашем случае MR3020. Когда он спросит устройство в сети, тогда ему придет ответ. В зависимости от скорости в сети RS485 и кол-ва переменных задержка может быть существенной (до 5-10 секунд). Передача данных по http методом POST/GET лишена этого недостатка.
azh122 писал(а):Щас решил объеденить все этим проектом (а то у меня еще одна сетка - в ввиде смарт розеток и выключателей - то же без сбоев. Причем не месяцы, а почти два года), плюс интелекта и статистики добавить.... Типа не стоит?
Думаю MR3020 не потянет MajorDoMo. Можно попробовать написать собственную CMS на php+SQLite используя lighttp. Может быть...
Пробовал на MR3020 mysql - если просто "крутиться" - то терпимо, если обрабатывать-записывать-читать - все, железка просто уходит в себя, даже SSH отваливается((
Было: Majordomo v.0.6.0.b на Cubietruck. OS Armbian с переносом на HDD
Стало: ioBroker на Cubietruck OS Armbian + ZigBee Xiaomi + OWFS + BLE.
azh122
Сообщения: 113
Зарегистрирован: Вт янв 28, 2014 5:33 pm
Благодарил (а): 1 раз
Поблагодарили: 6 раз

Re: Webserver (Arduino+W5100). Примеры интеграции с MajorDoM

Сообщение azh122 » Пт янв 31, 2014 7:06 pm

mr3020 и кучка дуин у меня работают примерно по такой схеме - http://www.cyber-place.ru/showthread.php?t=623
Обновление - раз в секунду, а не в 5 ( тем более не в 10), кстати. Хочу надстройку, которая все объединит. Подумал что этот проект может это сделать - хочу объединить - на DO поднял MajorDoMo и цепляю (точнее пока пытаюсь) к нему что есть. малинки, кубики и пр. - даже и не думал. Сначала отработаю (если получится) на нормальном железе (пусть виртуальном)
electric
Сообщения: 309
Зарегистрирован: Вт сен 17, 2013 10:11 pm
Благодарил (а): 3 раза
Поблагодарили: 56 раз

Re: Webserver (Arduino+W5100). Примеры интеграции с MajorDoM

Сообщение electric » Чт мар 27, 2014 10:00 pm

azh122 писал(а):mr3020 и кучка дуин у меня работают примерно по такой схеме - http://www.cyber-place.ru/showthread.php?t=623
Обновление - раз в секунду, а не в 5 ( тем более не в 10), кстати. Хочу надстройку, которая все объединит. Подумал что этот проект может это сделать - хочу объединить - на DO поднял MajorDoMo и цепляю (точнее пока пытаюсь) к нему что есть. малинки, кубики и пр. - даже и не думал. Сначала отработаю (если получится) на нормальном железе (пусть виртуальном)
Да, читал ваши записи, много что использовал для себя))
Было: Majordomo v.0.6.0.b на Cubietruck. OS Armbian с переносом на HDD
Стало: ioBroker на Cubietruck OS Armbian + ZigBee Xiaomi + OWFS + BLE.
Ответить