2016-01-28 грозния hack, който контролира лампите на фасата

by Vasil Kolev

Кодът, който пиша е грозна работа и пълен с hack-ове. Явно така ми харесва :)

Това е кодът, който контролира лампите по фасадата на лаба. Потрил съм малко от от вътрешната информация в него, като просто исках да се спра на няколко забавни неща в него.

Редове 11-18 се занимават с това да сменят статуса на лампите. Това, което правят е просто да сменят статуса на релетата на netcontrol-а, id-тата са от 13 до 15 включително (което отговаря на релета от 5 до 7, втория set в устройството).

Редове 20-39 се занимават с взимането на текущия state на системата:
– ред 23 взима дали е ден или нощ, от една малко patch-ната версия на sunwait. Сметката е сравнително проста, има я описана на доста места и се оказа един от най-лесните начини. (очаквах да има директно инструмент в debian, дето да ми го каже, но не открих такъв)
– ред 24 взима дали лампите са светнати, като взима статуса на едно от релетата. Това е малко некадърно, понеже поглежда дали е светната само една от лампите, но ме мързи да измисля по-приличен начин, който да лови неконсистентно светнати лампи. Също така това може да се направи доста по-човешко, без cut и awk.
– редове 26-29 питат контрола на входната врата дали е заключена или не (системата е описана във wiki-то на лаба).
– и редове 31-37 проверяват дали trigger-ът за форсиране на светването на лампите е вдигнат (който е един файл в /tmp)

Редове 41-44 са функция за печат на текущия статус, в общи линии за debug-ване.

Редове 47-53 инициализират един пакетен unix domain socket, който е в общи линии нещо като UDP socket – лесен начин за получаване на отделни съобщения. Инициализираме го за получаване, връзваме го във файловата система и го правим nonblocking.

На ред 56 ни започва главния цикъл.

В началото на цикъла се възползваме от socket-а (редове 57-61), като изчакваме или да се появи нещо на socket-а, или 60 секунди, което се случи по-рано. В първоначалната версия socket-ът го нямаше и имаше просто sleep(60), но така се налагаше да се изчака всеки път sleep-а, преди да се промени нещо. Така е възможно когато fauna-та получи информация, че вратата е отключена, да форсира демона да препровери състоянията и да светне лампите.
Тук може четенето от socket-а да се прави, докато не остане нищо в него, за да можем да се предпазим от DoS-ване, заедно с някакъв минимален timeout.

Нататък (редове 63-66) взимаме текущото състояние и dump-ваме малко информация.

На редове 68-70 правим проверка дали спрямо предишното състояние се е променил статусът на ключалката, и ако се е случило, отбелязваме кога. Това ни помага малко по-нататък.

Редове 73-84 хващат моментите, в които лампите са включени:
– Ако е ден и не сме форсирани от trigger-а, гасим лампите;
– Ако е нощ, вратата е заключена, не е вдигнат trigger-а и са минали 15 минути от заключването, гасим лампите. Така човек може да си тръгне спокойно от лаба и да не се пребие в тъмницата, като му угаснат лампите веднага като заключи.

Редове 86-97 обработват ситуацията, когато лампите са изключени:
– Ако trigger-ът е вдигнат, палим лампите;
– Ако е нощ и вратата е отключена (т.е. има хора в лаба), палим лампите.

Системата е кратка, цялата е един hack и работи прекрасно. Интегрира се лесно със съществуващите друг системи в лаба и ни дава още една доста полезна функционалност, и ни спестява да се сещаме да включваме лампите, когато навън е тъмно и railsgirls имат да идват към лаба :)

Tags: ,

6 Responses to “2016-01-28 грозния hack, който контролира лампите на фасата”

  1. antfarmer Says:

    А как точно си пипнал sunwait да ти плюе “day” и “night”?

  2. Vasil Kolev Says:

    @antfarmer, ами трябва да сипя някъде кода, доста е грозно, в общи линии в print.c си добавих функция и я викам:

    int print_day(int year, int month, int day,
                         double lat, double lon,
                         struct tm* tm, char local)
    {
      double daylen, civlen, nautlen, astrlen;
      double rise, set, civ_start, civ_end, naut_start, naut_end,
        astr_start, astr_end;
      double nw;
      int    rs, civ, naut, astr;
    
      daylen  = day_length(year,month,day,lon,lat);
      civlen  = day_civil_twilight_length(year,month,day,lon,lat);
      nautlen = day_nautical_twilight_length(year,month,day,lon,lat);
      astrlen = day_astronomical_twilight_length(year,month,day,
                                                 lon,lat);
    
      nw = TMOD(tm->tm_hour - (timezone_offset/3600)) + (double)tm->tm_min/60;
    
      rs   = sun_rise_set         ( year, month, day, lon, lat,
                                    &rise, &set );
    
      if ( nw>rise && nw<set)
        printf("day");
      else
        printf("night");
    
    }
    
  3. Бял кюнец Says:

    Съжалявам, че ще пиша в извънтемие, но не виждам къде другаде.

    От доста време не бях навестявал va.ludost.net/files. В началото на годината видях, че има много ново нещо. Към средата на миналата, като да бе „позанемарено“ (ъ, да от лаба има само три записа, но няма пак да говорим за т’ва).

    Обаче се сблъсках с проблем, който не съм имал преди. Когато тръгна да потегля нещо с wget и в името на филмчето има поне една кирилска буква, то ми изпищява:

    „Неправилен или непълен много-байтов или широк писмен знак“

    А например на ОФ ’15 имало някакъв младеж Kekäläinen, в чието име wget не намери никакъв проблем. Опитвах се да си сменя променливите на средата на нещо като цп1251, но това не даде резултат. Освен това потеглянето с kget (дори 3,5) проблем няма. С лисица няма. С Хром няма. Ама знайно е, колко е несгодно да се работи с графични клиенти, особено на място с ограничение до пет връзки, но не само.

    И понеже ти си нашият „местен господ“ пък и мястото е твое, не знам, към кой друг да се обърна за съвет, какво може да се объркало в тази примерно половин (или повече) година та wget ми крещи гробно, зловещо.

    Версията му е стандартна:

    $wget –version
    GNU Wget 1.16 built on linux-gnu.

    $ cat /etc/debian_version
    8.2

    и средата също е стандартна:

    $ env|grep bg
    LC_ALL=bg_BG.UTF-8
    LC_MESSAGES=bg_BG.UTF-8
    LANG=bg_BG.UTF-8
    LANGUAGE=bg_BG.UTF-8

    И баш е подразбиращият:

    $ bash –version
    GNU bash, версия 4.3.30(1)-release (i586-pc-linux-gnu)

    Нищо от това не е подменяно ръчно.

    Объркан съм. Подобно нещо съм виждал много отдавна, когато съм се опитвал да тегля неща именувани с cp1251, но тук случаят определено не е такъв.

  4. Vasil Kolev Says:

    @Бял кюнец, какво точно url ти дава? При мен https://va.ludost.net/files/of2015/Day2/Bulgaria/07.Collaboration%20In%20Open%20Source%20-%20How%20Does%20It%20Really%20Work%3f%20-%20Otto%20Kek%c3%a4l%c3%a4inen.mp4 си работи като слънце и се wget-ва, wget-а ми е същия и съм bg_BG.UTF_8.

  5. Бял кюнец Says:

    Първо трябва да се извиня, защото не съм се изразил ясно. Този човек има някакви странни букви в името си като „О“ с две точки (не знам как се казва самият знак). И поради това реших, че ако е счупена кодировка, трябва да се счупи и на него. НО! той си се тегли без проблем.

    Проблем има в имената на филмчета, в които има кирилица. Допълнително като правих опити, се оказа, че проблема частично е в мен. Нещата са доста големи, а лаптопа ми е с малък диск, затова ги записвам на външен. Обаче WD са го направили с ntfs. И тогава получавам съобщението:

    05.�%95лек�%82�%80онно гла�%81�%83ване – �%91ожида�%80 �%91ожанов.mp4: Неправилен или непълен много-байтов или широк писмен знак

    Cannot write to ‘05.\320%95лек\321%82\321%80онно гла\321%81\321%83ване – \320%91ожида\321%80 \320%91ожанов.mp4’ (Неправилен или непълен много-байтов или широк писмен знак).

    (от същият каталог, но независимо кой)

    Оказа се, че ако си свалям на родна ФС (в моя случай Рейзър 3), то нещата си се свалят. Но все пак има някакъв проблем. Защото се записват с имена като:

    05.?%95лек?%82?%80онно гла?%81?%83ване – ?%91ожида?%80 ?%91ожанов.mp4

    (Това е същият от горният пример)

    Такова нещо съм виждал, когато съм свалял някакви документи на word/excel очевидно правени под друга ОС (такива има в страницата на Любо от/за ТУЕС). Не разбирам защо част от знаците си ги разпознава коректно, друга не.

    Извинявам се отново, че се натресох на съвсем друга тема оплаквайки тегобите си. Най-вероятно проблема е в моя телевизор, но просто е нещо, което виждам горе-долу за втори път за последните 10 години. И ми е много чудно, какво съм окепезил.

  6. Бял кюнец Says:

    Само още нещо. Като поразгледах wget има зависимост от libidn11. Спомням си, че когато се качвах на 8,1 доста неща се счупиха, та трябваше ръчно да тегля пакети и да ги слагам отново. Бяха се счупили дори части от gnu utils (например cat), което ми се видя направо невъзможно. Още по-странно, че качването до 8,0 беше протекло напълно безпроблемно, независимо от пьотерингчетата вътре. Например vlc си ми е счупен и до днес. При него ръчната подмяна на пакетите му и зависимостите му, не помогна.

    Та се чудя да не би и libidn11 да се е счупила тогава, но да не съм разбрал. Дали има начин да проверя дали е работоспособна?!? Но все си мисля, че доста неща съм теглил от тогава и това ми е първият проблем.

Leave a Reply