niedziela, 18 listopada 2012

Logitech Solar K750

Gdy dni stają się krótsze, gdy słońca jest coraz mniej - używając linux'a zaczynasz się zastanawiać jak długo jeszcze będziesz mógł korzystać ze swej nowej klawiatury Logitech K750 Solar :). By rozwiązać ten problem, stworzyłem aplikację umożliwiającą odczyt danych z sensorów np. klawiatury k750, wszystko jest dostępne w projekcie na bitbucket.

Moje poszukiwania rozpocząłem od artykułu Julien Danjou, gdzie oprócz przejrzystego rozpracowywania protokołu Logitech'a został dodany później link do specyfikacji zdobytej przez Lars-Dominik Braun.

Jako że dość szybko odkryłem te informacje, uznałem że może ktoś już napisał jakąś aplikację wyciągającą stan baterii czy naświetlenia. Trafiłem na projekt na github'ie: https://github.com/aheadley/logitech-solar-k750-linux/blob/master/logitech_k750.py.

Niestety posiadał pewne wady:

  • nie do końca działał na moim sprzęcie
  • podczas odczytu wartości blokował cały interfejs usb - czyli klawiatura po prostu nie działała

Podczas poszukiwań mój cel stał się bardziej klarowny - postanowiłem napisać jakiś serwis pozwalający na bezproblemowy odczyt chociażby informacji o naładowaniu baterii.

Następnym problemem z którym musiałam się zmierzyć był fakt że wiele bezprzewodowych urządzeń logitech'a mogło korzystać z 1 odbiornika, powodowało to brak takowego podziału w urządzeniach /dev/hidraw, miałem nadzieję że patch proponowany na https://lkml.org/lkml/2012/1/17/118 mógłby to naprawić ale niestety to nie było to. Napisałem więc własny parser pakietów HID++ (których oczywiście nie mogłem znaleźć w specyfikacji :D ). Posiadam tylko jedno bezprzewodowe urządzenie logitech'a więc nie mogłem sprawdzić czy kod zachowa się poprawnie dla większej ilości.

Gdy już posiadałem kod potrafiący wyciągać i prosić o informacje o naładowaniu dodałem do tego serwis DBus, prostego klienta konsolowego oraz rozszerzenie do Gnome-Shell. Użytkownicy sytemu Gentoo mogą pobrać ebuild'a z https://bitbucket.org/glorpen/pysolar/src/tip/gentoo/app-misc/pysolar?at=default


Cała opisywania powyżej aplikacja jest dostępna jako projekt na bitbucket

poniedziałek, 12 listopada 2012

TinyMCE - Czy wysiwyg jest potrzebny?

wyswig

TinyMCE jest edytorem z kategorii wysiwyg - czyli “widzimy” jak treść będzie wyglądała po wyświetleniu użytkownikowi. Niestety nie zdarzyło mi się jeszcze zobaczyć tak przygotowanego edytora by rzeczywiście odwzorowywał style, nie mówię że jest to niemożliwe czy nawet bardzo trudne, po prostu najczęściej zaniedbywane - podstawowe style zazwyczaj działają (pogrubienie, kursywa, itp.).

Sądzę że najgorszym momentem jest gdy użytkownik będzie chciał dodać do treści widgeta złożonego z css/js, jako że tinymce jest edytorem html’a umożliwia wykonanie wszystkiego, nawet dodanie inlinowo do treści stylów i zewnętrznych javascript'ów a następnie węzła script z odpowiednim kodem inicjalizującym widget’a. Tak, będzie działało. Z punktu widzenia developera takie użycie zepsuje wiele dobrych praktyk - minifikacja, opóźnione ładowanie js (a co gdy np. jQuery jest załączane PO widgecie?),

Próbując znaleźć idealną odpowiedź na to pytanie, sporządziłem listę rzeczy która powinna być wspierana przez edytora:

  • prezentacja w jakiś sposób wyglądu końcowego
  • by użytkownik nie mógł “psuć” strony - załączać w treści nowych bibliotek, zmiana styli, dodawanie tagów skopiowanych z word’a czy też innych programów Microsoft’u
  • możliwość implementacji “interfejsów” przez developera - by użytkownik mógł w znormalizowany i kontrolowany przez developera sposób dodawać różne elemeny/widgety/embedować pliki

Dość szybko trafiłem na MarkItUp!. Pozwala on na zdefiniowanie własnego schematu który będzie później parsowany przez stronę serwerową, dostarcza możliwość podglądu aktualnie edytowanej treści (tutaj to samo ograniczenie co w tinymce - jeśli developer nie doda styli ze strony, podgląd nie będzie tak zbliżony do prawdziwego wyglądu jakby mógł być). Po stronie serwerowej wybrałem pythonowe Docutils z obsługą ReStructuredText (używane też na github’ie).

Plusy

  • Potrzeba sposobu na kolorowanie kodu? Nie ma problemu - wystarczy zarejestrować bibliotekę pygments jako funkcję w docutils
  • Dodawanie obrazka? Jest. Ma być po prawej? dodajemy align: right do opcji metody

W skrócie - trzeba dodać funkcjonalność X? Dodajemy nową funkcję rest_X do docutils :)

Minusy

  • Trzeba wiedzieć że jest to parsowane jako ReST
  • Znajomość struktury

Decyzję zostawiam wam :)

środa, 7 listopada 2012

Sprite’s i wiele teł

W czasach kiedy jeszcze studiowałem, na ćwiczeniach pojawiło się zadanie - napisać aplet którego głównymi bohaterami były drożdże. Minęło już dużo czasu od tego momentu ale hipnotyczne właściwości tej prostej aplikacji nie osłabły. Zdecydowałem sie więc na przepisanie jej na javascript'a - http://glorpen.pl/projects/yeast.

Tła przedstawiały stany danego pola i nie musiały występować same, tak więc potrzebowałem ustawić wiele teł dla pojedynczego elementu. Niestety jak na razie CSS nie wspiera rozszerzania deklaracji background. Napisałem więc następującego mixin’a:

@mixin yeast-background($theme, $args...){
  $positions: ();
  $backgrounds: ();

  @each $v in $args {
      $positions: append($positions, sprite-position($theme, $v), comma);
      $backgrounds: append($backgrounds, $theme, comma);
  }

  background: $backgrounds;
  background-position: $positions;
}

Jego użycie:

$theme: sprite-map("projects/yeast/themes/normal/*.png");

@include yeast-background($theme, background);

&.grass {
      @include yeast-background($theme, food, background);
  }
  &.carnivore {
      @include yeast-background($theme, thing, background);
  }
}

Co po skompilowaniu da nam mniej więcej coś takiego:

#project-yeast .app.normal td.grass {
 background: url('/static/img/projects/yeast/themes/normal-s1b3c760646.png'), url('/static/img/projects/yeast/themes/normal-s1b3c760646.png');
 background-position: 0 -64px, 0 -160px;
}
#project-yeast .app.normal td.carnivore {
 background: url('/static/img/projects/yeast/themes/normal-s1b3c760646.png'), url('/static/img/projects/yeast/themes/normal-s1b3c760646.png');
 background-position: 0 -96px, 0 -160px;
}