четверг, 19 марта 2015 г.

Протокол обмена

Надо придумать протокол обмена между управляющей программой (УП) и блоками. Напомню, связаны они по ethernet. 
Я остановился на tcp. Соединение устанавливает УП в начале работы и держит его постоянно. Когда УП нужно включить реле или диммер, она отправляет соответствующую команду.  Когда меняется значение входа, блок отправляет команду УП.
Пакеты с командами будут бинарными. Я вначале хотел использовать ascii формат, но парсить их не так удобно, а вручную к устройству проще обращаться по http через браузер.
Формат придумался такой - байт длины, байт команды, данные и crc16. 
Данные представляют собой простые упакованные структуры (а на avr выравнивания как раз нет). На питоне для упаковки/распаковки можно использовать встроенный модуль struct. Для расширяемости достаточно договориться, что смысл и размер имеющихся полей не меняется, а новые поля добавляются в конец пакета и игнорируются старыми версиями устройств.
Crc в tcp есть свое собственное, но оно обрабатывается отдельной платой (w5100 в ethernet шилде), а процессор от нее получает только данные. Вот для защиты от помех на spi crc и пригодится.
Реализовал описанное для реле и входов.

Ардуино

Штука очень симпатичная. Есть плата, к которой "бутербродиком" подключаются платы расширения, причем их полно всяких разных - ethernet, радио, что-то для роботов и т.п.
И есть среда разработки, в которой полно готовых примеров и библиотек для работы с самой ардуинкой и платами расширения. Там используется некий язык processing - по факту это с++ с некоторыми библиотеками и скрытой от пользователя функцией main()
В плату ардуино встроен usb-usart преобразователь, компьютер определяет ее как com-порт. В процессоре уже сидит загрузчик, который позволяет залить свою программу с компьютера без использования аппаратных программаторов.
Все это очень удобно для быстрого старта.

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

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

Итак, задача минимум - сделать программу вывода "hello world" в порт, построить проект, залить его на плату. Дальше прикрутить eclipse - и уже можно жить.

scons - это аналог make. В отличие от make - это программа на питоне и билд-файл также является программой на питоне, в которой доступны примитивы сконса. Это приводит к некоторым тормозам в процессе выполнения билд-файла, однако открывает широчайшие возможности - нам доступны все возможности языка программирования общего назначения и куча готовых библиотек для питона.

Компилятор и avrdude можно взять из установленной среды arduino, я скачал актуальные версии. avr-gcc у меня 4.9.2, со всей мощью с++11 :)

Сразу перейдем к результату.
Файл Sconstruct очень простой
e = Environment(tools=[(
                    'build', {
               'board':'UNO'})],
                toolpath=["../common"],
                COM='COM8')

e.ObjectH("test.cpp")
e.Libraries(['Ethernet', 'SPI'])

e.Prog('test')


Команда  scons в папке с проектом собирает программу. scons write=1 собирает программу и записывает ее на плату. Также эклипс настроен так, что информацию о путях и макросах он берет автоматически, вызывая тот же scons. Эклипс фактически используется как (очень) продвинутый редактор, все настройки компиляции - через scons.

Основная работа делается в файле build.py. Я выдрал из установленной среды файлы библиотек и ядра - мне так проще с точки зрения последующих модификаций. Также я вручную преобразовал в питоновские структуры информацию о платах из файла boards.txt. Можно было бы пойти по другому пути и сделать разбор файлов среды - брать оттуда ключи компиляции и т.п. - но мне пока это не нужно.

Готовый реп со всем этим добром доступен по ссылке

воскресенье, 25 января 2015 г.

Архитектура

У меня будет центральный сервер, в котором реализована вся логика, и простые исполнительные устройства. 
Хотелось бы, чтобы все это было по максимуму сосредоточено в шкафу.  Провода от каждой люстры и каждого выключателя сходятся в шкаф и там уже коммутируются. Т.е. мне нужны управляемые от компьютера входы и выходы. Основная масса входов - логические, выходы - реле и диммеры.  Также у меня есть 1wire термодатчики (температура в комнатах, подачи и возврата в коллекторе, пола), а еще аналоговые входы от датчиков освещенности. Аналоговый сигнал от датчика освещенности на большое расстояние передавать нельзя, его обрабатываем по месту и дальше отправляем в более устойчивом к помехам виде.
Как я вычитал на сайте ab-log.ru (автор - большой поклонник 1wire), этот сигнал хорошо передается на расстояния.
Итого - в щитке нужны логические входы, реле, диммеры, адаптеры 1wire. Вместе с датчиком освещенности ставим блочек с микропроцессором. К этому же блочку можно добавить вход ИК (управление от пульта ДУ) и выход ИК (управление кондиционером).
Я подумал и решил блочки сделать на базе ардуино (С пайкой у меня все плохо, поэтому платы должны быть уже готовые) .
* китайские клоны довольно дешевы - рублей 400
* есть готовые платы расширения
* быстрый старт - ставишь среду, подключаешь плату по usb и можно записывать программу. Есть много готовых библиотек
* возможностей меги328 хватит на все
Связь с этими блочками я думаю сделать через ethernet - просто подключать к компьютеру, а для ардуины есть готовая плата расширения и библиотека.
Теперь встал вопрос о блоках в шкафу. Нашел управляемые розетки для серверных - весьма недешевые, нет входов. 
На сайте ab-log есть готовый блок: 7 входов, 7 реле, управляется по ethernet, может работать автономно, крепится на динрейку. Я купил один на пробу. Что не понравилось
* довольно громоздкий.
* мне надо порядка 40 выходов и 90 входов - придется покупать 13 блоков,  часть выходов будет болтаться без дела
* очень неудобно сделано подключение. Клеммы под отвертку и маленькие - наконечник 1,5 засовывается с трудом, а сдвоенный уже не засунешь - расключение делать неудобно.
* нет диммеров
И тут я вспомнил, что мой работодатель как раз и занимается электроникой :)
В результате мне сделали вот такое чудо-юдо - 4 диммера, 32 входа, 16 реле, 1wire и ebus(для котла), крепление на динрейку. 3 блока в шкаф и один на замену. Мозги блока - те же ардуины, только на меге2560. Подозреваю, уместилось бы и в меги328, но на всякий случай сделал запас. 
 У такой меги 256к флеша, 8к ОЗУ и 4к епрома - есть где развернуться. Особенно если учесть, что сетевая библиотека почти ничего не весит - стек реализован в плате расширения.
Клеммники разъемные - mstb для выходов и более мелкие (забыл как называются) для входов. В mstb влезает сдвоенный 1,5 наконечник или одинарный 2,5.

суббота, 24 января 2015 г.

Дом, милый дом

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

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

Отопление
Установка желаемой температуры по комнатам, снижение температуры при отсутствии в доме.

Вода
Контроль утечки и автоматическое перекрытие воды.

На все это конечно есть готовые решения, Но
* цены негуманны. К примеру панель для котла стоила тысяч 12, но чтобы достучаться к ней удаленно, нужен отдельный блок, тысяч за 9. При этом система работает через сторонний сайт. А если я сменю модель котла, то все эти блоки можно выкинуть
* на освещение есть много готового, но между собой оно не совместимо. Затачиваться под вендора не хочется. Из бюджетных стандартных я нашел х10 - управляющий сигнал передается по электрической сети. Однако передача медленная и односторонняя (нельзя запросить выключатель/лампочку о своем статусе). Нужно специальное оборудование для прослушивания, подключения компьютера, сопряжения разных фаз
* хочется иметь единый сайт дома, на котором будет все
* и самое главное - я ж программист, а какой програмист откажется сделать велосипед

вторник, 11 сентября 2012 г.

svn и mercurial

svn

Я лет 5 сижу на работе на svn и тортилле. И все мне в них нравится, кроме того, что информация о мержах нигде наглядно не отображается. 5 лет назад svn вообще не умел хранить такую информацию и я завел привычку в комментарии к мержу указывать, с чем именно был сделан мерж. Примерно так:
[m657-549] Слито с веткой хххх
Это здорово выручает при всяких выяснениях. Проблема только в том, что чтобы получить наглядное представление о слияниях, надо брать карандаш и бумагу и рисовать интересующие ветки и мержи. Что задалбывает.
В svn 1.5 (а может и более позднем) появилось хранение информации о мержах в свойствах. Однако не знаю почему, но тортилла так до сих пор и не научилась показывать эту информацию на графе. Единственное, что она умеет с ней делать - при выборе ревизий для мержа уже смерженные "засериваются". Это приятно, но мало. Еще одна проблема с таким хранением - не знаю уж почему, но иногда эта инфа распространяется из корневой папки в дочерние папки и файлы. При этом при каждом мерже показывается куча объектов, у которых поменялись только свойства, а не содержимое. А так как фильтрануть по этому признаку можно не во всех диалогах, то это весьма надоедает.
Еще я иногда езжу в командировки, а иногда работаю дома (а иногда админы роняют сервер :) ). При этом хотелось бы также иметь доступ к своим репозитариям.

dvcs

Года полтора назад я начал присматриваться к распределенным системам. Гит мне как-то не глянулся своей линуксовой природой, да и начитался всякого о багах под виндой. Остались базар с меркуриалом.

Базар

Базар вроде как понавороченнее. Тут и легковесные ветки, куча форматов репа, "хитрые" номера ревизий, показывающие, откуда пришел мерж.
Однако его тортилла как-то не фонтан. Стартовое окно не сильно полезное, периодически вылетает, заставить ее использовать tortoise diff/merge я так и не смог. По дефолту во встроенном просмотрщике диффов используется utf-8, в то время как у меня в основном cp1251. Причем даже если поменять руками, то просмотрщик не сохраняет этих изменений. Сравнивать ворд или опенофис в отличие от tortoise svn не умеет. Обновление иконок сильно запаздывает. А когда выяснилось, что в путях с русскими буквами не пашет сравнение, причем это судя по моим изысканиям, бага самого базара, я в нем окончательно разочаровался.

Меркуриал

Меркуриаловская тортилла мне глянулась значительно больше. Падает она редко. По умолчанию открывается страница с журналом. Офисовские файлы сравнивать умеет (как я понял, скрипты для этого они позаимствовали у svn). Тортилловские diff и merge настроились влет. С русскими буквами проблем нет.
Не нравится только ее политика в отношении длинных сообщений - при показе в журнале она их режет до 80 символов (даже если место на экране еще есть), а при просмотре в окне всего сообщения не переносит по границам слов.
Но в принципе ладно, я согласен в случае длинного сообщения делать отдельную "выжимку", а после нее писать само сообщение.
Далее встал вопрос, как хранить центральные репозитарии. На сайте меркуриала обнаружилась масса полезных ссылок, в частности SCM-manager. Последний написан на яве и влет встал на уже имеющийся у меня на работе tomcat. Там же лежит ссылка на RhodeCode, который судя по скринам, понавороченней. Но с ним у меня пока не заладилось - при установке он попытался чего-то скомпилировать, компилятора на сервере нет, и я пока на него забил.
SCM-manager умеет раздавать mercurial и svn репозитарии, а также показывать их в браузере. Также для него можно настроить http-аутентификацию (что я легко сделал) и, судя по доке, относительно легко - ssl (на что я пока забил).

Нажитое

 Остался последний вопрос - что делать с уже имеющейся историей. В свое время при переходе с cvs на svn я истории лишился. Нормально перенести ее у меня не получилось, решил начать с нуля, а если что - смотреть историю в cvs. Однако после переустановки винды cvs-тулы я просто не поставил, а через некоторое время прочно забыл, как ими пользоваться и где вообще лежал мой реп :)
Так что теперь я решил все сделать по человечески. 
Меркуриал вроде как заявляет работу с svn с помощью встроенного расширения convert. Однако реп у меня устроен не по классической схеме - с иерархией в ветках и тегах, с несколькими транками, иногда изменения делались прямо в тегах, проектов в нем штук 15, и лежат они в одном общем транке. Кроме того, я отмечал мержи и не хочу их лишиться.
С помощью convert мне удалось максимум вытащить ветку, причем начиная с момента ее создания (т.е. до начального ее копирования из другой ветки).
Тогда я вспомнил, что базар тоже работает с svn и попробовал конвертацию свн->базар->меркуриал. Эта схема оказалась лучше - мне удалось скопировать ветку целиком (начиная с ревизии 1). Однако это все равно не то, что мне надо.
Тогда я решил написать свой собственный конвертер. Писал я его на питоне. Вроде как все несложно - с svn я работаю через pysvn (скомпилированная версия для винды есть на офсайте), а с меркуриалом - просто через командную строку.
Меркуриал позволяет при коммите указать дату и пользователя. Осталось только заново "проиграть" всю историю.
Однако вожусь я с этим вот уже третью неделю (в свободное от основной работы время, но все же). Вылезла масса всяких нюансов - переименование тегов, положенные в svn бинарные файлы (я  сдуру когда-то запихал туда инсталлированный компилятор :) ), ветки, созданные из тегов, ошибки при коммитах, ....
Так что программа-конвертер разрослась уже за 1000 строк и местами весьма запутанна. Кроме того, прилагается немаленький файл с исключениями :)
Хорошей идеей оказалось прикрутить diff и в ключевых точках (например в тегах) делать автоматическое сравнение рабочих копий hg и svn. Еще одна хорошая идея - с шагом в несколько ревизий делать бэкапы репозиториев hg - чтобы при ошибках начинать не с начала. 
Пока удалось сконвертить чуть больше четверти репа, посмотрим что вылезет дальше



пятница, 8 июля 2011 г.

Перечисления

В последнее время мне полюбился вот такой способ задания всякого рода перечислений:
1 #define SOME_ENUM_PRINT(P) \ 2 P(eNone, 0, "Нет") \ 3 P(eCmd57_Ok, 1, "Команда 57 ОК") \ 4 P(eCmd57_Cancel, 2, "Команда 57 Отмена") \ 5 P(eCmd58, 4, "Команда 58") \ 6 P(eTimer, 8, "Таймер") \ 7 P(ePrintOk, 16, "Печать завершена") \ 8 P(ePrintError, 32, "Ошибка печати") 9 10 enum ESomeEnum { 11 #define P(n, no, s) n = no, 12 SOME_ENUM_PRINT(P) 13 #undef P 14 }; 15 16 // а потом можно вот так: 17 const char * str(ESomeEnum e) 18 { 19 switch(e) 20 { 21 #define P(n, no, s) case n: return s; 22 SOME_ENUM_PRINT(P) 23 #undef P 24 default: return "Unknown"; 25 } 26 }

Понятно, что кроме текста, можно добавить произвольную информацию.  С помощью такого макроса легко строить всякие таблицы, создавать куски кода, работающие с каждым членом перечисления и т.д. Как бонус, если изменить перечисления, то многие связанные с этим вещи обновятся автоматически. Ну и последнее - вся информация в одном месте.
При этом все довольно просто и понятно Улыбка На рсдн была статья, в которой описывалось как создавать “строгие” перечисления и ассоциировать с ними доп инфу. Однако код в ней значительно сложнее Улыбка

среда, 29 июня 2011 г.

Склероз

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

А потом, через полгода-год старая задача снова становится актуальной. Но я уже почти все о ней забыл. Остались какие-то смутные воспоминания и рабочие записи, в которых теперь ничего не понятно. И снова все начинается заново – читаешь доки, наступаешь на те же грабли. Что-то конечно вспоминается, но далеко не все.

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

Видимо надо завести правило – если работа над задачей остановилась больше чем на неделю, то надо потратить день-два и подробно (очень подробно) все записать по горячим следам.

Кстати, рекомендую http://trac.edgewall.org/ – хорошая система учета доки, багов, записей и заодно просмотр коммитов в системе контроля версий. Без проблем ставится под виндоуз, причем в простейшем варианте не требуется веб-сервер.