Какие бывают веб-интерфейсы для управления умным домом. Фитбеки от Microsoft. Все что мы сделали - фигня

Мы смогли научить нашу систему «умный дом» распознавать сказанное нами и синтезировать голосовые ответы при помощи Google.
Сегодня я хочу рассказать, как организовать доступ к нашей системе через веб-интерфейс.

Технологии

Как вы помните, ПО для управления нашим «умным домом» мы пишем на языке perl . Современная информационная система практически немыслима без БД. Мы тоже не останемся в стороне и для хранения наших данных будем использовать СУБД MySQL . Для реализации веб-сервера я решил воспользоваться не сторонним софтом, а модулем для perl - HTTP::Server::Simple , в частности - HTTP::Server::Simple::CGI . Для чего я это сделал? В большой части, ради интереса;) Но в теории, можно получить доступ к низкоуровневой обработке HTTP-запросов/ответов без нагромождения комплекса Apache/mod_perl. В целом, ничего не мешает перевести проект на рельсы Apache, если у вас будет желание и достаточно времени.

База данных

Первым делом установим СУБД MySQL и создадим базу с таблицами из db.sql. Вот листинг:

CREATE DATABASE ion; USE ion; # # Table structure for table "calendar" # DROP TABLE IF EXISTS calendar; CREATE TABLE `calendar` (`id` int(15) NOT NULL AUTO_INCREMENT, `date` datetime NOT NULL, `message` text, `nexttimeplay` datetime NOT NULL, `expired` datetime NOT NULL, `type` int(1) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1; # # Table structure for table "commandslog" # DROP TABLE IF EXISTS commandslog; CREATE TABLE `commandslog` (`id` int(15) NOT NULL AUTO_INCREMENT, `date` datetime NOT NULL, `cmd` varchar(255) NOT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; # # Table structure for table "log" # DROP TABLE IF EXISTS log; CREATE TABLE `log` (`id` int(15) NOT NULL AUTO_INCREMENT, `date` datetime NOT NULL, `message` varchar(255) NOT NULL, `level` int(1) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

Выполним необходимые действия:

Nix@nix-boss:~$ sudo apt-get install mysql-server
nix@nix-boss:~$ mysql -uroot -ppassword < db.sql

Модифицируем код

Теперь нам необходимо создать папки lib , html и config (рядом с папкой data ). В папку lib мы положим модуль, отвечающий за реализацию веб-сервера и обработку наших HTTP-запросов.

Нам нужно немного подправить скрипт srv.pl . Добавим к блоку инциализации:

Our %cfg = readCfg("common.cfg"); our $dbh = dbConnect($cfg{"dbName"}, $cfg{"dbUser"}, $cfg{"dbPass"});
Добавим строки, отвечающие за запуск HTTP-сервера ниже блока инициализации:

## Запуск HTTP-сервера ################################ my $pid = lib::HTTP->new($cfg{"httpPort"})->background(); print "HTTP PID: $pid\n"; logSystem("Сервис HTTP - PID: $pid, порт: $cfg{"httpPort"}, хост: $cfg{"httpHost"}", 0); ################################
А теперь добавим недостающие функции в конец файла:

Sub readCfg { my $file = shift; my %cfg; open(CFG, "; foreach my $line (@cfg) { next if $line =~ /^\#/; if ($line =~ /(.*?) \= \"(.*?)\"\;/) { chomp $2; $cfg{$1} = $2; } } close(CFG); return %cfg; } ######################################## sub dbConnect { my ($db, $user, $pass) = @_; return $dbh = DBI->connect("DBI:mysql:$db", $user, $pass) || die "Could not connect to database: $DBI::errstr"; } ######################################## sub logSystem { my ($text, $level) = @_; my %cfg = readCfg("common.cfg"); dbConnect($cfg{"dbName"}, $cfg{"dbUser"}, $cfg{"dbPass"}); $dbh->do("INSERT INTO log (date, message, level) VALUES (NOW(), "$text", $level)"); }

Как можно понять по названиям функций, dbConnect() - отвечает за соединение с нашей СУБД, logSystem() - за логгирование, readCfg() - за загрузку конфигурации. Остановимся на ней подробнее. Конфигурация представляет собой простой текстовый файл в директории config. В нашем случае, он называется common.cfg . Выглядит примерно так:

## Настройки daemonMode = "undef"; logSystem = "1"; logUser = "1"; dbName = "ion"; dbUser = "root"; dbPass = "password"; camNumber = "4"; camMotionDetect = "1"; httpPort = "16100"; httpHost = "localhost"; telnetPort = "16000"; telnetHost = "localhost"; micThreads = "5";

Некоторые строки в нем будут использованы позже. Нас же пока интересуют только строки, начинающиеся с префикса db . Как мы видим - это настройки для соединения с нашей БД.

Теперь расскажу о том, как побороть многократное выполнение команды. Подредактируем функцию checkcmd() :

Sub checkcmd { my $text = shift; chomp $text; $text =~ s/ $//g; print "+OK - Got command \"$text\" (Length: ".length($text).")\n"; if($text =~ /система/) { ################################################# my $sth = $dbh->prepare("SELECT cmd FROM commandslog WHERE DATE_SUB(NOW(),INTERVAL 4 SECOND) <= date LIMIT 0, 1"); $sth->execute(); my $result = $sth->fetchrow_hashref(); if($result->{cmd} ne "") { return; } $dbh->do("INSERT INTO commandslog (date, cmd) VALUES (NOW(), "$text")"); ################################################# if($text =~ /провер/) { my $up = `uptime`; $up =~ /up (.*?),/; sayText("Время работы сервера - $1. Номер главного процесса - $parent."); } if($text =~ /врем/) { my $up = `uptime`; $up =~ /(.*?) up/; sayText("Сейчас $1"); } if($text =~ /законч/ || $text =~ /заверш/) { sayText("Завершаю работу. Всего доброго!"); system("killall motion"); system("rm ./data/*.flac && rm ./data/*.wav"); system("killall perl"); exit(0); } if($text =~ /погод/) { my ($addit, $mod); my %wh = lib::HTTP::checkWeather(); $wh{"condition"} = Encode::decode_utf8($wh{"condition"}, $Encode::FB_DEFAULT); $wh{"hum"} = Encode::decode_utf8($wh{"hum"}, $Encode::FB_DEFAULT); $wh{"wind"} = Encode::decode_utf8($wh{"wind"}, $Encode::FB_DEFAULT); if($wh{"temp"} < 0) { $mod = "ниже нуля"; } if($wh{"temp"} > 0) { $mod = "выше нуля"; } $wh{"wind"} =~ s/: В,/восточный/; $wh{"wind"} =~ s/: З,/западный/; $wh{"wind"} =~ s/: Ю,/южный/; $wh{"wind"} =~ s/: С,/северный/; $wh{"wind"} =~ s/: СВ,/северо-восточный/; $wh{"wind"} =~ s/: СЗ,/северо-западный/; $wh{"wind"} =~ s/: ЮВ,/юго-восточный/; $wh{"wind"} =~ s/: ЮЗ,/юго-западный/; sayText("Сейчас $wh{"condition"}, $wh{"temp"} градусов $mod. $wh{"hum"}. $wh{"wind"}"); if ($wh{"temp"} <= 18) { $addit = sayText("Одевайтесь теплее, на улице холодно!"); } if ($wh{"temp"} >= 28) { $addit = sayText("Переносной кондиционер не помешает!"); } } } #sayText("Ваша команда - $text"); return; }
Мы выбираем последнюю выполненную команду в интервале четырех секунд и если она совпадает с текущей - выходим из функции. Как вы можете заметить, я добавил некоторые команды, по сравнению с описанной функцией в прошлой статье. Наиболее интересная - это погода. Реализация получения данных для нее - чуть ниже.

Модуль HTTP.pm

Вернемся к реализации встроенного HTTP-сервера. Создадим файл HTTP.pm в директории lib . Запишем туда следующий код:

Package lib::HTTP; use HTTP::Server::Simple::CGI; use LWP::UserAgent; use URI::Escape; use base qw(HTTP::Server::Simple::CGI); use Template; ######################################### ######################################### our %dispatch = ("/" => \&goIndex, "/index" => \&goIndex, "/camers" => \&goCamers,); our $tt = Template->new(); ######################################### ######################################### sub handle_request { my $self = shift; my $cgi = shift; my $path = $cgi->path_info(); my $handler = $dispatch{$path}; if ($path =~ qr{^/(.*\.(?:png|gif|jpg|css|xml|swf))}) { my $url = $1; print "HTTP/1.0 200 OK\n"; print "Content-Type: text/css\r\n\n" if $url =~ /css/; print "Content-Type: image/jpeg\r\n\n" if $url =~ /jpg/; print "Content-Type: image/png\r\n\n" if $url =~ /png/; print "Content-Type: image/gif\r\n\n" if $url =~ /gif/; print "Content-Type: text/xml\r\n\n" if $url =~ /xml/; print "Content-Type: application/x-shockwave-flash\r\n\n" if $url =~ /swf/; open(DTA, "<$url") || die "ERROR: $! - $url"; binmode DTA if $url =~ /jpg|gif|png|swf/; my @dtast = ; foreach my $line (@dtast) { print $line; } close(DTA); return; } if (ref($handler) eq "CODE") { print "HTTP/1.0 200 OK\r\n"; $handler->($cgi); } else { print "HTTP/1.0 404 Not found\r\n"; print $cgi->header, $cgi->start_html("Not found"), $cgi->h1("Not found"), $cgi->h2($cgi->path_info()); $cgi->end_html; } } ## Обработка запроса / ######################################## sub goIndex { my $cgi = shift; # CGI.pm object return if !ref $cgi; my %w = checkWeather(); my $cmd; my $dbh = iON::dbConnect($iON::cfg{"dbName"}, $iON::cfg{"dbUser"}, $iON::cfg{"dbPass"}); my $sth = $dbh->prepare("SELECT cmd FROM commandslog WHERE id > 0 ORDER BY id DESC LIMIT 0, 1"); $sth->execute(); my $result = $sth->fetchrow_hashref(); if($result->{cmd} ne "") { $cmd = $result->{cmd}; } else { $cmd = "Нет комманд..."; } print "Content-Type: text/html; charset=UTF-8\n\n"; my $uptime = `uptime`; $uptime =~ /up (.*?),/; $uptime = $1; my $videosys = `ps aux | grep motion`; if ($videosys =~ /motion -c/) { $videosys = "работает"; } else { $videosys = "не работает"; } my $micsys = `ps aux | grep mic`; if ($micsys =~ /perl mic\.pl/) { $micsys = "работает"; } else { $micsys = "не работает"; } my $vars = { whIcon => $w{"icon"}, whCond => $w{"condition"}, whTemp => $w{"temp"}, whHum => $w{"hum"}, whWind => $w{"wind"}, cmd => $cmd, uptime => $uptime, video => $videosys, mic => $micsys, threads => $iON::cfg{"micThreads"}, }; my $output; $tt->process("html/index", $vars, $output) || print $tt->error(), "\n"; } ## Обработка запроса /camers ######################################## sub goCamers { my $cgi = shift; # CGI.pm object return if !ref $cgi; my %w = checkWeather(); my $cmd; my $dbh = iON::dbConnect($iON::cfg{"dbName"}, $iON::cfg{"dbUser"}, $iON::cfg{"dbPass"}); my $sth = $dbh->prepare("SELECT cmd FROM commandslog WHERE id > 0 ORDER BY id DESC LIMIT 0, 1"); $sth->execute(); my $result = $sth->fetchrow_hashref(); if($result->{cmd} ne "") { $cmd = $result->{cmd}; } else { $cmd = "Нет комманд..."; } if($cgi->param("text") ne "") { my $txt = $cgi->param("text"); require Encode; $txt = Encode::decode_utf8($txt, $Encode::FB_DEFAULT); iON::sayText($txt); } print "Content-Type: text/html; charset=UTF-8\n\n"; my $vars = { camera1 => "video-0/camera.jpg", camera2 => "video-1/camera.jpg", camera3 => "video-2/camera.jpg", camera4 => "video-3/camera.jpg", whIcon => $w{"icon"}, whCond => $w{"condition"}, whTemp => $w{"temp"}, whHum => $w{"hum"}, whWind => $w{"wind"}, cmd => $cmd, }; my $output; $tt->process("html/camers", $vars, $output) || print $tt->error(), "\n"; } ## Погода ######################################## sub checkWeather { my %wh; my $ua = LWP::UserAgent->new(agent => "Mozilla/5.0 (Windows NT 5.1; ru-RU) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.872.0 Safari/535.2"); my $content = $ua->get("http://www.google.com/ig/api?hl=ru&weather=".uri_escape("Санкт-Петербург")); $content->content =~ /(.*?)<\/current_conditions>/g; my $cond = $1; $cond =~ /

Разберем содержимое подробнее. В хэше %dispatch мы определяем соответствие URL-адреса и вызываемой функции. Все прочие URL, не описанные в этом хэше, будут выдавать страницу 404 .
Шаблонизатором у нас будет выступать мощная и гибкая библиотека Template Toolkit . Её мы инициализируем строкой:

Our $tt = Template->new();
Перегружая функцию handle_request() родительского класса, мы получаем управление обработкой запросов к HTTP-серверу. Для отдачи браузеру статического контента (png, gif, jpg, css, xml, swf) используется блок:

If ($path =~ qr{^/(.*\.(?:png|gif|jpg|css|xml|swf))}) { my $url = $1; print "HTTP/1.0 200 OK\n"; print "Content-Type: text/css\r\n\n" if $url =~ /css/; print "Content-Type: image/jpeg\r\n\n" if $url =~ /jpg/; print "Content-Type: image/png\r\n\n" if $url =~ /png/; print "Content-Type: image/gif\r\n\n" if $url =~ /gif/; print "Content-Type: text/xml\r\n\n" if $url =~ /xml/; print "Content-Type: application/x-shockwave-flash\r\n\n" if $url =~ /swf/; open(DTA, "<$url") || die "ERROR: $! - $url"; binmode DTA if $url =~ /jpg|gif|png|swf/; my @dtast = ; foreach my $line (@dtast) { print $line; } close(DTA); return; }
Так как MIME-типов у меня получилось немного, я записал их чуть по-индусски;)
Дальше начинаются функции, отвечающие за генерацию контента определенного URL. Пока их всего две - индекс и страница с камерами.
На индексе мы сможем увидеть, работают ли такие подсистемы, как видео- и аудио-захват. Отдельной строкой идет:

My %w = checkWeather();
Эта функция возвращает хэш с текущими данными о погоде в городе, которые будут отображаться на нашей странице. Такая мелкая приятная плюшка;)
Там же рядом мы будем выводить последнюю полученную и распознанную команду для «умного дома».

Следующая функция goCamers() выполняет те же функции, что и индекс, только вместо вывода информации по состоянию подсистем, показывает изображение с наших камер и имеется возможность написать какой-либо текст, который будет синтезирован и озвучен нашим «умным домом».

Все странички строятся на основе шаблонов, лежащих в папке html . Выкладывать листинг здесь будет не удобно, поэтому дам ссылку на архив -

Повествование с краткими техническими отступлениями.

Как все начиналось

История эта началась почти полтора года назад. К нам пришел заказчик с «проектом мечты».
Заказ звучал коротко и просто: изменить дизайн UI текущей системы умного дома.
Взглянув на систему, было видно типичного представителя умного дома, каких сейчас множество, вот она в старом дизайне.
А именно: унылые иконки взятые из сети, непродуманная логика экранов, не эргономичное использование пространства маленького разрешения, гламурные градиентные кнопки, и датчики на плане этажа сделанные так, как получилось у программиста.


Но архитектура проекта представляла из себя довольно грамотное решение. Был сервер управления датчиками и анализа данных, представляющий из себя маленькую коробочку, к которому можно было подключиться тремя способами:

  • С домашнего компьютера через браузер (как к роутеру) в административный интерфейс - для настройки всего и вся
  • С сенсорной панели при входе в дом - для управления сигнализацией, сценариями, камерами и датчиками (с нее нам было и предложено начать)
  • С мобильных устройств - для управления домом из любого места (в первом варианте через туже админку)

Переговорив с заказчиком, решено было делать интерфейс в стиле Windows 8, хотя сама она тогда еще не вышла, были лишь многочисленные скриншоты в сети. Опустим подробности такого решения, скажу лишь, что оно было принято единогласно и мы приступили к работе.
Тут стоит упомянуть, что у нас к тому времени был некоторый опыт проектирования интерфейсов близких по духу: панель управления яхтами (они достойны отдельных статей, но там NDA жесткое), бортовой компьютер авто и пяток сенсорных киосков.

Идея

Тема проектировки системы умного дома давно будоражила мое воображение. Решения, что существуют на рынке, и близко не приближаются к тому, что я могу назвать «Умным».

Рассмотрим пример

Стемнело. Вам нужно включить свет в комнате. Ваши действия?
Как это происходит обычно - вы встаете и включаете свет.
По версии многих разработчиков систем автоматизации - вы берете пульт и включаете свет.
Часто тут не видят банальных проблем. Во-первых, пульта рядом может и не быть, надо-таки встать, чтобы его найти, во-вторых, не забываем, что большинство таких устройств сейчас с сенсорным экраном, это означает, что пульт нужно еще и включить. Новая мода - делать пульт с планшета или телефона (отдельное приложение), что еще больше усложняет задачу:
Встать и найти устройство - > Включить или разблокировать экран -> Запустить приложение - > Найти нужный датчик - > Профит.
Не проще ли встать и включить выключатель?
Умный дом в моем понимании - должен сам включить свет тогда, когда это вам необходимо, при этом учесть бодрствуете вы или отдыхаете, время года, количество людей в комнате, ваше местоположение в комнате и еще кучу факторов, основываясь на предыдущие ваши решения в подобных ситуациях, предугадывая ваши желания. Иначе, дом этот сложно назвать «умным».
Пульт же - должен использоваться лишь частных случаях и не должен являться основным элементом управления домом. По-настоящему, «Умным» домом" вообще не нужно управлять - он все сделает сам.

Но до таких систем еще далеко, можно сказать, реализовать это сегодня невозможно, поэтому будем улучшать то, что можем, а именно, тот самый пульт.

Главную проблему этих решений проще показать знакомой хабру картинкой:

Да, почти все подобные системы - это пульты управления ядерным реактором, в которых сложно порой разобраться даже продвинутому пользователю.
Разработчики почему-то стараются поместить на экран как можно больше элементов, как можно больше возможностей и, как следствие, как можно больше проблем UX.

Так в чем же идея?

Убрать с глаз долой все лишнее, абсолютно все.
Если я хочу просто выключить свет в спальне, зачем мне видеть датчики управления водяными клапанами на кухне?
Если мне хочется закрыть все окна в доме, то я хочу делать это одной кнопкой, а не тыкать в каждый датчик по отдельности.
Если я ставлю дом на сигнализацию и в доме никого нет - это значит, что свет везде должен быть погашен, температура понижена, окна закрыты, включено видеонаблюдение. И все это должно произойти без моего участия!

Одно кольцо, чтобы править всеми Одна кнопка - «Сделать хорошо».

Лучший интерфейс тот - которого вы не видите, на который вы не обращаете внимание во время работы, который делает все за вас, либо же вы управляете им на подсознательном уровне, потому что:
а) вы привыкли так
б) это очевидно
Обращаете ли вы внимание на то, где находиться кнопка Play на Youtube? Где кнопка закрытия окна браузера? Или где поле поиска в Google?
А введет ли вас в ступор сотня датчиков на одном экране системы умного дома?
Верно, все, что на самом деле требуется от подобных систем - решить одну какую-то конкретную задачу (как Play в плеере или Find в поиске). Поэтому нет смысла выводить все возможное управление на экран.

Не такая простая задача на самом деле.

Первый прототип.

От заказчика мы получили его видение примерно так:

Посмотрели, подумали, и единственное, что использовали из его материалов, это спецификации датчиков и команд (сценариев пользователя)
Нас загоняло в рамки несколько моментов:

  • В сенсорной панели не было поддержки MultiTouch и она имела разрешение 1024*768 и 1024*600
  • Metro интерфейс был новым и не было возможности пощупать его на планшетах (8-ка еще не вышла). Хотя у нас был телефон на WP7, что давало некоторое представление.
  • Заказчик некоторые моменты в системе не мог изменить (железные ограничения, удорожание системы, личные хотения, и тп)

В целом сделать дизайн таких экранов как: главное меню, видеонаблюдение и интерком, погода за бортом, уведомления системы и подобных - не составило проблем, да и незачем об этом рассказывать, это была 1-я версия, дальше будет интереснее.
Проблемным был лишь основной экран управления датчиками. О нем и напишу.

План дома

Вот картинка типичного экрана управления датчиками с планом дома взятая из интернета:

Скажите, многие ли из вас понимают, что нарисовано на этом плане?
А поймет ли этот план ваш ребенок? А ваша бабушка? А друг, зашедший на чаек, сориентируется?
Думаю проблема понятна.

План должен быть читаем всеми и сразу. Для этого на нем должен быть виден именно ваш дом, с вашим цветом стен и основной мебелью:

А в идеале, план еще должен быть всегда позиционирован относительно сторон света.
Такое решение дороже, да и перестановка мебели сделает план не точным, но тут в любом случае - компромисс. Впрочем, ничто не мешает включить в проект любой план, либо же и вовсе без него (такое решение нами тоже было спроектировано).
Кстати, в первых версиях для премиум класса хотели сделать план в 3D, но решение сильно дороже, да и лишнее это, перспективы - вполне достаточно.

Датчики

Самая большая проблема - визуальное представления датчиков управления на плане решилась быстрее чем ожидалось. Как сейчас помню, мы с дизайнером сидели и рисовали на бумаге WireFrames будущей системы, и решение пришло само собой:

Ниже я прикрепил видео, где видно как это работает.

Одна кнопка

«Ну и где же тут одна кнопка?» - спросите вы.
А вот где:
«Одна кнопка» - это условность, под этим я понимаю одну функцию - самую важную и вынесенную на передний план.
Разрешение у нас маленькое, показывать на нем красочный план и утыкав его датчиками «по самое не хочу» - плохая идея.
Стоит вспомнить, что сейчас я описываю создание стационарной версии пульта (т.е. это монитор вмонтированный в стену).
Основные сценарии типового использования этой панели таковы:

  • Человек открывает входную дверь - > активируется панель и предупреждает нас, что нужно отключить сигнализацию - > вводится пароль - > активируются сценарии заданные для этого дома.
  • то же самое при выходе из дома - ставим на сигнализацию
  • Если кто-то звонит в дверь - смотрим кто, через интерком, который показывается поверх любого экрана при звонке с улицы и открываем дверь.
  • Активация пользовательских сценариев - например режим «Ночь», когда двери и окна запираются, включается видеонаблюдение, снижается температура и пр.

Управление отдельными датчиками с этой панели не очень-то удобно (ну сами посудите, вы будете настраивать яркость света в спальне, находясь в коридоре?)
Управление возможно, если панели встроены по всему дому.
Но, по словам заказчика, функция эта там необходима, нужно делать.

Решение

При входе на экран, пользователь видит только план дома. Датчики видны в виде очень маленьких точек (для того, чтобы знать где они).
Кроме возможности переключить этаж у пользователя всего 2 варианта:
1) Активировать панель опций, что позволит, например, вывести все термостаты в доме на план и настроить температуру как не предусмотренно сценариями, или, например, активировать розетки в гараже.

2) Увеличить план. Чем больше увеличиваем - тем больше датчиков превращается из маленькой точки в полноценный контрол управления, датчики появляются в зависимости от приоритета. Тем самым не загромождая собой пространство.

Т.е. пользователь всегда видит только то, что ему необходимо.

Интеграция

Решение заказчика было на WPF, а интеграция дизайна в XAML, это основная моя специализация. Поэтому мы не только «рисовали картинки», но и реализовывали дизайн на практике.
О том, как мы делали контролы и их XAML, все это анимировали и привязывали к плану дома, можно написать отдельную большую статью, но чем меньше знают конкуренты, тем более ценны мы как специалисты. Да и нет особого смысла описывать решение стационарного пульта, т.к. далее речь пойдет о планшетной версии.

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

В сумме на проектирование, дизайн и его реализацию в демо приложение, которое в дальнейшем ушло программистам заказчика уже непосредственно для привязки железа и логики, у нас ушло около 5 месяцев.
И, как обычно это бывает, сделав проект - всегда хочешь его переделать, потому что уже видишь, как сделать его лучше, его недостатки и слабые места, а слабых мест тут было много.

Пока я делал XAML, вышла Windows developer preview, и я тут же поспешил ее потрогать на десктопе и на своем планшете (Aser Iconia W500). Так же вышли официальные Guidlines, что позволило взглянуть на Metro UI по-новому.

Часть 2.

Все что мы сделали - фигня

Заказчик был очень доволен, особенно когда мы презентовали рабочую демку. Можно сказать, счастью его не было предела. Я видел недостатки проекта, но в тоже время знал, что довести до идеала его можно лишь работая над ним много времени в паре с командой хороших программистов, но это не имело значения на данном этапе развития продукта.
Заказчик, как и я, уже посмотрел новую Windows 8, и мы оба считали, что она очень хороша. Поэтому на мое предложение: «А давайте сделаем версию для планшета?», отреагировал очень положительно. Я предложил не менять встраиваемую в стену систему, т.к. она не поддерживала MultiTouch, ставить туда восьмерку не было смысла. Её редизайн оставили до лучших времен, сосредоточившись на Metro/Windows store приложении (именно Metro, т.к. это позволит распространять демку в маркете для привлечения клиентов).
К сожалению, бюджет у заказчика оказался не резиновый, но я согласился, по сути версию для Windows 8 мы подарили. Отчасти это было необходимо, у нас была очень хорошая работа в портфолио еще до релиза восьмерки.

Второй прототип.

Через пару недель мой дизайнер предоставил мне свое видение планшетной версии продукта:


Полную версию дизайна можно

Я был немного расстроен, дизайн был далек от того что было нужно, я попытался объяснить ошибки, но нельзя научиться плавать не залезая в воду, дизайнер не мог дать мне то, что я хотел, потому что тогда у него было слишком мало опыта общения с Windows 8.

Поэтому было решено все переделать, но вести работу над дизайном совместно со мной, делая все сразу в XAML.
Это решит проблему нехватки скилов по Guidlines у дизайнера, а мне, как разработчику, не даст испортить картинку.

Дизайн V2 и одновременная интеграция

Честно сказать, это было чертовски сложно. Я готов был убить разработчиков Blend 5, ибо по сравнению с 4-й версией, это было глючное, неработоспособное, постоянно вылетающее чудовище. Сейчас дело обстоит получше, но некоторых моментов не хватает.
Меня спасла VS 2012, в нее частично включили функционал бленда для управления стилями.
Новый XAML - это тема отдельного разговора, половины старых классов нет, дефолтные стили никуда не годятся, триггеры удалили - оставив только не богоугодные Visual States. Так же пришлось переписать проект с нуля когда Win 8 обновилась до Relize Preview, но те изменения были в лучшую сторону.

Новая концепция

Новое устройство - новый подход. Пришлось пересмотреть идею стартового экрана, теперь он был не нужен, а вся навигация выносилась в верхний AppBar.
Долой все кнопки с экрана: Zoom - жестом, у нас же полноценный MultiTouch, все управление датчиками - в нижний AppBar.
Теперь приложение стартует сразу с показа плана дома (в идеале оно должно отслеживать в какой комнате находиться пользователь и сразу ее немного увеличивать позиционируя по центру).

Открываем приложение:

Делаем жест Zoom (или мышкой CTRL+колёсико):

Или достаем AppBar:

Контролы

Контролы датчиков пришлось переписать с нуля, и сделать их нативными с нормальной поддержкой жестов Windows 8.
Было учтено, что теперь у нас управление 2-мя способами, пальцами и мышью.
Так же был вылизан внешний вид датчиков, стало более стильно:


Особенно наповал сразила скорость работы приложения. Производительность в Windows8 приложениях на порядки выше WPF. Я боялся, что планшет не осилит систему, но все просто летает. Microsoft превзошли самих себя, теперь не имеет значения насколько сложен XAML, все будет работать быстро. Если в WPF приходилось делать самопальные алгоритмы кеширования экранов для быстрой анимации, думать над сложностью ветвления XAML, оптимизировать количество элементов в дереве контрола, то в восьмерке, это просто не имеет значения, анимация любой сложности и любого количества объектов всегда плавная.

Вариант без плана


Тут были не нужны датчики с поддержкой жестов, не нужно было экономить пространство. Получилось конечно не так эффектно, но хорошо.

Сценарии

Управление датчиками, это конечно хорошо, но, как я уже писал, базовые операции с ними лучше автоматизировать.
Для этого в административном интерфейсе есть базовые предустановки сценариев и возможность создания своих.

На планшете это выглядит так:

Одна кнопка

От этой концепции мы не отходили с самого начала.
Часто задают вопрос: «А где тут работы на полгода?»
И это я воспринимаю как похвалу. Это значит, я добился того - чего хотел. Пользователь просто не видит, что функционал приложения - довольно большой, ведь видно только то, что нужно на данный момент. Данные и необходимые экраны сами показываются пользователю, а не он ищет их. Интерфейс понятный с первых минут, не пугающий обилием кнопок и в тоже время любое действие выполняется на «раз - два - три».
На создание только версии под Windows 8 ушло 3 месяца (c учетом наработок в первой версии, с нуля было бы больше).

К слову. Вы замечали, что везде в Windows, такой элемент как PopUp - всегда один? Чтобы мы не открыли, всплывающая форма - всегда одна, если открыть другую - предыдущая закроется. У меня в интерфейсе была беда: датчик после активации закрывался через определенное время сам, но если активировать один, а потом другой сразу - они были открыты оба, выглядит не очень эстетично и понятно. Спасибо моему второму дизайнеру за этот фитбек. Он не принимал непосредственного участия в проекте, но некоторые вещи реализованы благодаря его наводкам.
Я неделю бился над решением этой проблемы.
И я ее решил…
Одной строчкой кода.
Мораль: иногда за самыми простыми решениями скрывается очень много работы.

Фитбеки от Microsoft

Прошлой весной Microsoft проводила акцию, где все разработчики могли получить бесплатные рекомендации по улучшению UI/UX своих продуктов. И мы успели на эту раздачу.
Если честно, то я боялся что разнесут все в пух и прах, это же был мой первый опыт с восьмеркой. Но, все прошло гладко, по словам заказчика, в Microsoft очень высоко оценили качество приложения. Мы получили несколько небольших рекомендаций по улучшению юзабилити (к слову очень грамотных) например это:


Очень верное замечание, берите на заметку. Если мы выделяем какой-то объект и далее возможны действия с ним - AppBar должен открыться сам! Показав пользователю эти самые возможные действия.
Вообще проблема гораздо шире, озвучу так - очевидные действия должны выполняться сами, не нужно ждать, когда это сделает пользователь.

Все поправки я внес менее чем за день. И на душе стало тепло и спокойно.

Итого

На данный момент система находиться в стадии разработки, у заказчика не так все хорошо, как хотелось бы. Поэтому и пишу пост спустя почти год, дата релиза неизвестна и сейчас.
Приложение можно потрогать из Windows Store тем у кого стоит Windows 8, но перед этим нужно поставить в настройках Турецкую локаль:
Панель управления->Время, язык и регион ->Регион -> Изменение расположения - > Турция (потом не забудьте вернуть, иначе маркет вам будет показываться Турецкий)
Но сейчас в Store лишь урезанная версия, демонстрируюшая основные возможности. Когда-нибудь система будет доделана, а так как мы переделывали старую - вероятность этого велика. Надеюсь, у заказчика дела пойдут в гору и мы продолжим работу над проектом. А работы там еще очень много: web версия, сайт, фирменный стиль (мы разработали лишь логотип и его идею, но надо развивать), версия под iOS, Android, WP8. да и версию под Windows 8 я бы сейчас немного переделал, мы ее закончили прошлым летом, с тех времен в WIndows много что поменялось, да и мои скилы в этой области подросли.

Ну и напоследок видео про версию на Windows 8 (cмотрите HD)

Есть еще видео от заказчика, но оно уж очень плохого качества.

PS. Об ошибках в статье пишите в личку.

Арт-директор Лев Эйдинов поделился с редакцией сайт рассказом о концепте SmartShell - приложения для «умного» дома, в котором задействовал дополненную реальность.

Я давно изучаю сферу интернета вещей и «умной» электроники. На мой взгляд, это будущее, от которого никуда не уйти. «Умные» телефоны и телевизоры, часы и автомобили, - сейчас этим никого не удивишь. И в дальнейшем количество вещей с приставкой «смарт-» будет неуклонно расти. Это тема для отдельной беседы, а сегодня я хочу затронуть тему «умного» дома, а конкретнее - его интерфейса.

Несмотря на то, что системы «умного» дома предназначены для облегчения жизни людей, интерфейсы систем контроля выглядят сложно, перегружено и нелогично. Большинство представляет собой непонятную, графически шумную мешанину.

Я полностью согласен с парадигмой «лучший интерфейс - это отсутствие интерфейса», поэтому попытался максимально упростить взаимодействие пользователя с экосистемой «умного» дома. Хочу представить вашему вниманию концепт SmartShell - интерфейс «умного» дома в дополненной реальности.

Датчики и актуаторы (устройства, исполняющие команды: выключатели, розетки, водные клапаны) - основные «действующие лица» экосистемы «умного» дома. В системе SmartShell каждый актуатор имеет виртуальное отображение, через которое пользователь управляет устройством.

Наводя камеру смартфона на область помещения, человек сразу видит подключенные устройства. Именно это и делает управление простым и необременительным. Интерфейс построен на стандартных элементах iOS - это позволяет минимизировать время на обучение.

Наводя смартфон на области помещения, пользователь видит подключенные устройства и может управлять ими. Но за простым интерфейсом кроются технические, внутренние сложности. Самая большая из них - позиционирование.

Обычно в приложениях «умных» домов используются системы позиционирования смартфона (GPS, ГЛОНАСС, сигнал от вышек связи), которые не дают нужной точности и не всегда корректно работают в помещении. Для решения этой задачи предлагается использовать синергетическое позиционирование, основанное на совместном анализе данных, полученных от разных источников:

Используя взаимодействие вышеописанных систем, можно получить точность позиционирования 20 см, что является приемлемым для данной концепции.

Итак, запуская приложение, пользователь попадает на основной экран. В центре окно камеры, в котором отображаются подключенные устройства.


В этом режиме интерфейс может работать в альбомной ориентации.


Каждому устройству соответствует выделенная область в дополненной реальности («проекция актуатора»), рядом находится иконка соответствующего раздела. Всего разделов, выводимых на главный экран, пять: «Климат», «Медиа», «Свет», «Безопасность» и «Приборы». Они расположены в нижней части экрана и по умолчанию включены.

При переключении контроллера в режим «Схема» подключенные устройства отображаются на схеме помещения. Это удобно, когда нужно задействовать устройства вне зоны видимости. Температура указывается в центральной части помещения. Масштаб регулируется стандартным разводом пальцев.

При нажатии на кнопку раздела в нижней части экрана перестают отображаться соответствующие ему устройства. Повторное нажатие вновь активирует отображение. На экранах ниже включены разделы «Медиа» и «Свет» в режимах «Камера» и «Схема». Устройства остальных разделов не отображаются.

Нажимая на выделенную область, пользователь попадает на страницу управления актуатора. Для каждого устройства задаются собственные параметры, которые можно регулировать.


Названия устройств можно редактировать. Это помогает пользователю быстрее ориентироваться и запоминать устройства. Кнопка «Питание» расположена в самом верху, чтобы предотвратить случайные нажатия. Доступ к настройкам, наоборот, упрощен.

Как говорилось ранее, каждое устройство снабжено Bluetooth-маяком, который помогает в позиционировании, а также передает информацию о температуре устройства.

Система различает команды, противоречащие сценарию автоматизации. Например, светильник в центре зала (первый экран выше) можно включить в любое время, хотя таймер включения установлен на определенные часы. Пол на кухне (второй экран выше) установлен на включение при температуре ниже 20 ˚C. Включение при более высокой температуре собьет настройки, и пользователь увидит предупреждение:

Управление. При нажатии на меню-гамбургер в левой части основного экрана пользователь переходит на страницу управления.

Структура панели «Управление» включает в себя разделы устройств (с добавленным разделом «Сантехника»), счетчики и статистику, управление компонентами, конфигурацией дома и так далее.

Для простоты навигации первый уровень меню выполнен в виде раздвижного списка. В разделах устройств на этом уровне можно выбрать тип устройства.

На втором уровне можно выбрать конкретное устройство из списка. Здесь же присутствует общая настройка группы устройств. С ее помощью можно, например, выставить одинаковую температуру на всех кондиционерах или выключить весь свет.

Третий уровень меню открывает настройки, диагностику и управление определенного устройства.

Выбрав «Управление» мы попадаем на уже знакомую страницу управления конкретным устройством.

Интерфейс – это то, что пользователю «умного дома» приходится видеть и осязать каждый день. Поэтому понятному и отлично продуманному интерфейсу отводится важное место в интеллектуальной системе. Он должен отражать основные задачи и не перегружаться излишними функциями и компонентами. Качественный интерфейс умного дома – это непременная составляющая системы, он является гарантом удобного и эффективного управления интеллектуальным домом, с которым легко и просто управляется пользователь.

Что такое интерфейс

Под этим определением понимается метод взаимных действий между пользователем и системой посредством конкретного устройства, и в данном рассматриваемом случае – это сенсорная панель .

Чтобы получать от взаимодействия с ним комфорт и удовольствие, необходимо разрешить главные вопросы интерфейса: как будет выглядеть дисплей? Какие должны быть на нем отображены кнопки? Легко ли будет поменять функции, которые уже есть? Как упростить поиск нужных параметров?

Что включает интерфейс

Если рассматривать его в более широком толковании, то он представляет собой базу, в которой собраны различные способы контакта пользователя с системой «умный дом». «Общение» с ней, достигается с использованием разных устройств.

Например:

  • сенсорной панелью;
  • пультом дистанционного управления;
  • кнопочными панелями выключателями и панели;
  • мобильным телефоном посредством звонков GSM и СМС-сообщений;
  • устройством управления с помощью Интернета (компьютер, планшет, смартфон);
  • голосовым управлением.

Каким он должен быть

Система «Умный дом» — это сложная структурная композиция. Однако внутренняя сложность не должна являться таковой при ее использовании, а быть как можно проще. Чем нужно руководствоваться при выборе интерфейса.

Вот главные принципы:

  • Простота и удобство . Управление сценариями и функциями не должно отнимать много времени, а делаться разовыми кликами. Интерфейс должен быть понятен и прост как для родственников в возрасте, так и для детей. И только необходимая информация должна поступать на экран, а иконки быть такими, чтобы их легко можно было узнавать. Понятный и логичный алгоритм управления.
  • Безопасность . Интерфейс должен предоставлять возможность блокировки некоторых функций во избежание запуска нежелательной функции посторонним людям или детям. Отдельные страницы должны защищаться паролем.
  • Гармоничный дизайн . Интеллектуальный дом должен быть красив во всем. И интерфейс не исключение, поскольку каждое устройство, будь то контроллер или сенсор, является неотъемлемой частью интерьера и должен быть гармонично вписан в дизайн. Не должны выделяться из него даже встроенные панели, а быть лицом интерьера. Благо существует множество цветовых оттенков, обложечных графических тем и иконок, чтобы создать единый стиль.

Всем этим требованиям вполне отвечает, например, веб-интерфейс умного дома блочно-колоночной организации. К примеру, первый блок или группа их задействуется на камерах наблюдения для отражения информации, второй – на системе отопления, третий – на устройствах энергетики, чтобы проводить индикацию состояния устройств или потребления энергии.

В заключение

Нормальное системное функционирование не может быть обеспечено без интерфейса. Принцип работы универсального средства управления основывается в первую очередь на возможности выхода в Интернет, то есть на той платформе, которая дает возможность контролировать комплексно системы автоматизации. Кроме этого интерфейс интеллектуальной системы умного дома служит гарантом информационного контакта и поддержки функциональности.

Система должна иметь совместимость с любым персональным компьютером или мобильными устройствами, имеющими разные платформы.

Также как и общие интерфейсы, в систему включены локальные средства функционального управления. В большинстве своем они представлены разного рода выключателями, сенсорными и клавишными панелями, имеющими узкий функционал.

Например, устройство, которое установлено в комнате на одной из стен, может управлять освещением и климатом. Нажатием клавиш вы определяете необходимые операции – включаете слабый свет, поднимаете температуру в помещении и т.д. Можно включить ряд функций сценарий.



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: