Szaf(k)a gra!

marzec 30th, 2008

Mam już na koncie całkiem sporo projektów - dużych i małych i tych napisanych “do szuflady”. Każdy staram się wykonać jak najlepiej, ale zawsze jest tak, że projekt albo “mi leży” albo “mi nie leży”. Najbardziej lubię projekty, które wychodzą poza środowisko serwera web i wchodzą w interakcję z otoczeniem mniej lub bardziej “fizycznym”.

Najnowszym takim projektem - cały czas we wczesnej fazie dev ;) - jest domowa skrzynka muzyczna sterowana przez web.

Jak to działa?

Sercem jest stary komputer z prockiem AMD Duron 900 MHz ustawiony w szafce w kuchni, żeby w pokoju była cisza. Do niego podłączone są głośniki ustawione już w pokoju. Całość podłączona jest do Sieci, dzięki czemu mogę sterować muzyką przez komórkę z Operą Mini, a w przypływie ochoty mogę posłuchać radia internetowego (np. Groove Salad).

Jak to jest zrobione?

Całkiem prosto. Oto lista potrzebnych rzeczy i softu:

  • komputer - 1 sztuka
  • kabel skrętka - w zależności od potrzeb, w moim przypadku 15 m
  • przedłużacz audio (mały jack) - w zależności od potrzeb
  • system operacyjny - Linux (ja użyłem dystrybucji Debian)
  • mpd (music player daemon) - soft grający, działa jako demon, nie ma interfejsu i sterowany jest przez sieć
  • mpc (konsolowy soft sterujący mpd)
  • mplayer - do odtwarzania stacji radiowych
  • serwer WWW (Apache) z obsługą PHP
  • konto na no-ip.org

Krok I

- instalujemy na komputerze Debiana (lub co tam wolicie), do tego mpd i mpc. I tutaj mała uwaga - dostępna przez apt-get wersja jest nieco stara i ma bug powodujący, że po zatrzymaniu ogdrywania (np. pauza) nie można wznowić odgrywania. Dlatego należy całość skompilować ze źródeł. Strona projektu: musicpd.org

Krok II

- komputer wynosimy tam, gdzie będzie najmniej przeszkadzał, podłączamy do sieci, podłączamy głośniki. Rejestrujemy się na no-ip.com i instalujemy klienta no-ip.com na maszynie

Krok III

- sterować możemy z konsoli, używając klienta mpc. Nie o to jednak chodziło. Ja interfejs zbudowałem w oparciu o PHP. Od strony użytkownika jest to przeglądarkowe klikadło wykorzystujące Ajax (jquery.com - świetnie działa w Operze Mini). Jeżeli zaś chodzi o komunikację z mpd - połączenie z portem 6600 localhosta. MPD ma własny, dość prosty protokół. Do sterowania playerem przygotowałem prostą klasę:


<?php
class ncmpdcommander{
var $fpStream;

function ncmpdcommander($sServer, $iPort){
$this -> fpStream = fsockopen($sServer, $iPort);
//stream_set_blocking($this -> fpStream, 0);
$sResoponse = fread($this -> fpStream, 1024);
}

function disconnect(){
fclose($this -> fpStream);
}

function doCommand($sCommand){
fwrite($this -> fpStream, $sCommand . "\n");

while(trim($sLine) != 'OK'){
$sLine = fgets($this -> fpStream, 512);
if(trim($sLine) != 'OK'){
$sResponse .= $sLine;
}
}
return $sResponse;
}

function playbackNext(){
$this -> doCommand('next');
}
function playbackPrev(){
$this -> doCommand('previous');
}
function playbackStop(){
$this -> doCommand('stop');
}
function playbackPlay(){
$this -> doCommand('play');
}
function playbackPause(){
$this -> doCommand('pause');
}

function getTitle(){
$sStatus = $this -> doCommand('currentsong');
preg_match('!file: (.+)!', $sStatus, $shFound);
$sTitle = $shFound[1];
preg_match('!([^/]+)\.mp3$!', $sTitle, $shFound);
$sTitle = $shFound[1];
$sTitle = preg_replace('!^[0-9 _-]+!', '', $sTitle);
$sTitle = str_replace('_', ' ', $sTitle);

return $sTitle;
}

function getPlaylist(){
$sPlaylist = $this -> doCommand('playlist');
$saPl = explode("\n", $sPlaylist);
foreach($saPl as $sItem){
list($iNum, $sTitle) = explode(':', $sItem, 2);
$saPlaylist[$iNum] = $sTitle;
}
return $saPlaylist;
}

function volumeUp(){
$this -> doCommand('volume +10');
}
function volumeDown(){
$this -> doCommand('volume -10');
}
}

?>

Samo wykorzystanie klasy jest już banalne:

<?php
require_once('ncmpdcommander.class.php');

$oCmd = new ncmpdcommander('localhost', 6600);
switch($_GET['cmd']){
case 'next':
$oCmd -> playbackNext();
break;
case 'prev':
$oCmd -> playbackPrev();
break;
case 'stop':
$oCmd -> playbackStop();
break;
case 'pause':
$oCmd -> playbackPause();
break;
case 'play':
$oCmd -> playbackPlay();
break;

case 'get-title':
echo $oCmd -> getTitle();
break;

case 'volume-up':
$oCmd -> volumeUp();
break;

case 'volume-down':
$oCmd -> volumeDown();
break;
}

$oCmd -> disconnect();
?>

To już koniec

Nie opisałem całości w szczegółach, mam jednak nadzieję, że ten opis zainspiruje Was do przygotowania czegoś podobnego. A może już coś takiego macie? Piszcie w komentarzach o Waszych projektach wychodzących poza przeglądarkę!

Pozdrawiam i do następnego wpisu!

Ten w okularach to ja 8-)

luty 11th, 2008

Niestety, nie mam ostatnio zbyt dużo czasu na pisanie bloga. Pracy nad kilkoma już projektami nie ubywa a wciąż pojawiają się nowe. Zapewniam Was jednak, że blog nie umarł - nadal o nim pamiętam, zatwierdzam komentarze i w miarę możliwości kończę czekające na publikację artykuły.
W życiu zawodowym pojawiło się kolejne wyzwanie: CeBIT 2008. Firma MASTER TELECOM jako jedna z około 30 polskich firm (wszystkich wystawców ma być ok 5500) będzie miała przyjemność przedstawić swoją ofertę na tych największych targach IT. W Hanowerze przedstawimy trzy nasze projekty:

Zapraszam więc na nasze stanowisko na targach CeBIT w dniach 4 - 6 marca 2008. Hala 9, stanowisko D05:

Mapa

mapa_b.png

MASTER TELECOM na CeBIT

Gdy już traficie na nasze stoisko, pamiętajcie: ten w okularach to ja 8-)

Bo komputer winien posłuszeństwo swemu panu

grudzień 3rd, 2007

Chciałbym zachęcić Was do podzielenia się waszymi przyzwyczajeniami i zwyczajami które wyrobiliście sobie podczas programowania. Chodzi mi o wasze warsztaty - jakich narzędzi (edytorów, menedżerów plików etc) używacie na co dzień, i
bez jakich programów nie wyobrażacie sobie wygodnego programowania. Ja sam używam Vim’a. Na tę okazję przygotowałem stronę z krótkim opisem moich ulubionych pluginów, kolorów i sztuczek. Ta strona to dopiero początek. Cały czas będę ją rozwijał i dodam opisy kolejnych programów. Zapraszam Was do zapoznania się ze stroną Vim the editor i do komentowania oraz chwalenia się ustawieniami, programami i narzędziami których używacie.

Dobra komunikacja

listopad 13th, 2007

Ostatnie miesiące to przede wszystkim wytężona praca nad nowym projektem, który wczoraj miał swoją premierę. Ten projekt to połączenie oprogramowania CRM z Contact Center w modelu ASP (Application Service Provider). Ten projekt to serwisowa.pl.

serwisowa.pl to nie tylko oprogramowanie pozwalające zarządzać bazą danych klientów i ich sprzętu, ale także system wychodzący poza internet i integrujący w sobie kilka kanałów komunikacji. Podstawowym kanałem jest telefon. Każde połączenie telefoniczne klienta z usługodawcą jest w sposób przezroczysty dla obu stron odnotowywane w systemie. Dzięki temu, jeszcze przed odebraniem połączenia, konsultant ma możliwość sprawdzenia, który klient dzwoni (klienci są identyfikowani numerem karty klienta) i sprawdzenia dotychczasowej histori kontaktów. Jeżeli dostawca wybrał opcję rejestrowania połączeń, klient jest informowany o tym przed połączeniem a rozmowa jest rejestrowana i udostępniana do odsłuchania zarówno dostawcy usług jak i klientowi. Gdy nie ma możliwości połączenia z dostawcą, klient może pozostawić wiadomość w poczcie głosowej.

Połączenie telefoniczne to tylko jedna z możliwości odebrania zgłoszenia od klienta. Dostępny jest także formularz zgłoszeniowy. O każdym nowym zgłoszeniu, dostawca może być informowany za pomocą wiadomości SMS i e-mail.

Przedstawione opcje, to dopiero początek. Kolejne wersje systemu przyniosą przede wszystkim zwiększenie ilości dostępnych kanałów komunikacyjnych, oraz API pozwalające zintegrować serwisowa.pl z innymi systemami. Wkrótce postaram się przybliżyć możliwości integracji, oraz kilka zastosowanych rozwiązań technicznych. Teraz jednak zapraszam do zapoznania się z naszym nowym systemem: serwisowa.pl

serwisowa.pl

Domena z www - nie twórzmy niepotrzebnych ograniczeń

wrzesień 16th, 2007

Problem

Po wpisaniu w Google zapytania jak wybrać domenę, otrzymamy w przybliżeniu 1,320,000 wyników. Jak widać, jest dość popularne zagadnienie. Każdy, kto zakłada własną stronę, może dowiedzień się jak wybrać piękną, unikalną domenę, sugerującą korzyści, jakość produktu, łatwo wymawianą, łatwą do zapamiętania… bla bla bla. Część z tych artykułów ociera się już o bełkot, choć można przeczytać także coś wartościowego.

Dziwi mnie jednak, dlaczego tak wielu administratorów stron (adminów, webmasterów i im podobnych) nie zauważa problemu subdomeny www? Bardzo często spotykam się z sytuacją, gdy jedynym działającym adresem strony jest www.example.org, natomiast example.org nie wskazuje na żaden serwer, albo - co gorsze - wskazuje na stronę firmy hostingowej.

Dziwi mnie niesamowicie to, że wiele firm walczy o jak najkrótsze nazwy, nieraz odkupując domeny za duże pieniądze. Po czym cały efekt jest psuty przez nieudolnego admina/webmastera etc, bo do ślicznej, trzyliterowej domeny trzeba dopisać kolejne 4 znaki - www. Złego wizerunku strony dopełnia fakt, że w gros przypadków nie ma żadnego uzasadnienia w wymuszaniu na użytkownikach dopisywania www.

Osobiście wpisując adresy stron, niemal zawsze pomijam www. Często niestety kończy się to koniecznością ponownego wpisania adresu - tym razem z www. Irytuje mnie to bardziej niż “strona przygotowana dla IE 5¼”. Szczególnie, że rozwiązanie problemu jest niesamowicie banalne, a zaniechanie - w mojej opinii - wynika jedynie z ignorancji adminów.

Rozwiązanie I (dobre, z wadami) - dajemy wybór internautom

Dosyć dobrym rozwiązaniem jest takie skonfigurowanie sewera www, aby dla obu adresów (example.org i www.example.org) zwracał tę samą stronę. W Apache można np. skonfigurować dwa wirtualne hosty wskazujące na to samo położenie dokumentów - DocumentRoot.

Dzięki takiemu rozwiązaniu, obojętnie czy odwiedzający wpisze www.example.org czy example.org - zawsze zobaczy stronę której szuka.

Wady rozwiązania I

Internauta jest zdezorientowany

Mniej doświadczeni internauci (np. ci, którzy na e mówią “Internet”) mogą czuć sie zdezorientowani, a nawet zagrożeni tym, że jakaś strona ma adres bez www na początku.

Możliwe rozwiązania: wykorzystać Rozwiązanie II lub zignorować problem ;)

Przeglądarka jest zdezorientowana

Należy pamiętać o tym, że przeglądarka odsyła ciasteczka tylko do tych domen, do których powinna je odesłać. Jeżeli więc w PHP ustawiamy ciasteczko w ten sposób:


setcookie('kruche', 'z_cukrem');

to nie dziwmy się, że użytkownik który np. zalogował się na example.org/login/, nie będzie zalogowany na www.example.org/.

Możliwe rozwiązania: ustawiajmy ciasteczka korzystając z opcjonalnych parametrów setcookie:

bool setcookie ( string $name [, string $value [, int $expire [, string $path [, string $domain [, bool $secure [, bool $httponly]]]]]])

Czyli możemy napisać tak:

setcookie('kruche', 'z_cukrem', time() + 60 * 60 * 24 * 31, '/', '.example.org');

ciasteczko będzie widoczne dla wszystkich subdomen naszego serwisu.

Takie podejście do ciasteczek jest bardzo ważne. Znam serwis, który działa pod dwoma adresami: example.org i www.example.org. Można w tym serwisie dokonać płatności za zamówienie za pośrednictwem jednego z systemów płatności online. Jednak powrót z systemu transakcyjnego następuje zawsze na adres www.example.org. Wiadomo jaki jest efekt: gdy loguję się na example.org - zamiast potwierdzenia płatności, otrzymuję ekran logowania…

Innym problemem jest zapamiętywanie haseł i wartości wpisanych w formularzach przez przeglądarki. Wartości te są także przypisywane do domen. Jeżeli zapamiętam hasło na example.org/login/, to nie będzie ono proponowane przez przeglądarkę na www.example.org/login/

Możliwe rozwiązania: Rozwiązanie II

serwer jest zdezorientowany

Przy korzystaniu z dwóch wirtualnych hostów, w zależności od konfiguracji serwera, możemy mieć problem np. ze statystykami (odzielne statystyki dla www.example.org i example.org) lub ze skonfigurowaniem SSL. Niektóre roboty i wyszukiwarki mogą traktować adresy www.example.org i example.org jako niezależne strony (choć zdaje się, że Google już sobie z tym poradziło).

Możliwe rozwiązanie: Rozwiązanie II

Rozwiązanie II (dobre) - odbieramy wybór internautom

W tym rozwiązaniu należy dać wybór internautom, przez skonfigurowanie serwera tak, aby działały oba adresy (www.example.org i example.org) - tak jak w Rozwiązaniu I - a następnie odebrać wybór przez ustawienie przekierowania na jednym z adresów. Takie rozwiązanie możemy zrealizować na dwa sposoby:

Apache i mod_rewrite

Używamy mod_rewrite w Apache aby przekierować użytkownika z example.org na www.example.org. Można to zrobić np. tak:

<VirtualHost 127.0.0.1>
ServerName example.org
DocumentRoot /var/www/i/co/tam/jeszcze_chcecie
RewriteEngine On
RewriteRule ^/(.*)?$ http://www.example.org/$1?%{QUERY_STRING} [R=301,L]
</VirtualHost>

Moje ulubione rozwiązanie. Jest o tyle dobre, że przekieruje użytkownika bez utraty ścieżki i parametrów przekazanych metodą GET. Wady: dane przekazane metodą POST zostaną utracone.

PHP i header()

Jeżeli nie macie możliwości modyfikowania konfiguracji Apache, podobne rozwiązanie można uzyskać korzystając z PHP i funkcji header():

if($_SERVER['HTTP_HOST'] == 'example.org'){
header("Location: http://www.example.org{$_SERVER['REQUEST_URI']}");
die();
}

i po problemie!

Jak widać, można bez problemu skonfigurować serwer tak, aby działały obie domeny - www.example.org lub example.org. Cała trudność polega jedynie na zauważeniu problemu. W zależności od potrzeb możemy skorzystać z któregoś z rozwiązań. W obu jednak trzeba pamiętać o tym, że serwery DNS muszą zwracać IP serwera dla obu domen.

Apel dnia ;)

Nie narzucajmy sztucznych i niepotrzebnych ograniczeń!

Takim niepotrzebnym ograniczeniem jest właśnie wymaganie wpisywania www lub to o którym pisał kiedyś Robert Drózd: Za krótkie - źle, za długie - też źle.

2^8 dzień roku

wrzesień 13th, 2007

W 28 dniu roku, wszystkim programistom życzę wszystkiego najlepszego z okazji Dnia Programisty. Ciekawy jestem, jak go obchodzicie…

Systemy komunikacji

czerwiec 5th, 2007

Wpis z pierwszego kwietnia był oczywiście żartem, ale tylko w części. Prawdą w nim jest to, że pożegnałem się ze swoim dotychczasowym pracodawcą i nie pracuję już nad systemami SIECI T2.

Teraz, wraz z grupą profesjonalistów pracuję nad nowymi, nowatorskimi systemami, także związanymi z komunikacją IP. Pierwsze wdrożenia i sukcesy już za nami, a praca nad nowymi produktami trwa w najlepsze!

Wszysktich zainteresowanych zapraszam:

teleakademia.pl

Idzie nowe…

kwiecień 1st, 2007

Ponieważ wczoraj ostatecznie rozstałem się ze swoim dotychczasowym pracodawcą, postanowiłem iść za ciosem i dokonać w swoim życiu jeszcze większych zmian in plus. Rezygnuję z pracy związanej z internetem gdyż jest on zupełnie pozbawiony przyszłości i nie daje sensownych perspektyw rozwoju. Z tym niszowym (i ciągle tracącym na popularności) medium nie można wiązać żadnych nadziei.

Dlatego właśnie zmieniam branżę na garmażerię. W naszym pędzącym świecie, w którym ludzie mają coraz mniej czasu nie tylko na odpoczynek ale także na przygotowanie zdrowych i pożywnych a zarazem smacznych i regenerujących posiłków, tylko przemysł garmażeryjny daje jakiekolwiek nadzieje na rozwój zawodowy.

Jedną z konsekwencji mojej decyzji, będzie oczywiście zmiana tematyki tego bloga. Już teraz mogę zdradzić tematy przyszłych wpisów:

  • Naleśniki - optymalizacja procesu smażenia
  • Kopytka - bezpieczeństwo gotującego
  • Klient - kuchnia - zarządzanie relacjami
  • Jaja na miękko - wydajniejsza kontrola czasu gotowania
  • Pierogi - optymalizacja struktury farszu
  • Patelnia przemysłowa - przykładowa konfiguracja
  • Kelnerzy i dostawcy - zasadność użycia proxy

Smacznego!

Wydajniejsza kontrola dostępu do plików - virtual()

luty 23rd, 2007

Problem

Bardzo często istnieje potrzeba zrealizowania zaawansowanej kontroli dostępu do plików, przy czym standardowe mechanizmy Apache nie wystarczają. Dzieje się tak, gdy decyzja o tym, czy plik należy udostępnić jest podejmowana przez aplikację na podstawie informacji niedostępnych dla serwera (np. stan punktowy konta użytkownika lub inne warunki wynikające z logiki aplikacji).

Szybkie rozwiązanie

Pierwszym rozwiązaniem, które przychodzi na myśl, jest użycie PHP i funkcji operujących na plikach - np. file_get_contents():


<?php
if(allowFileDownload($sFile)){
echo file_get_contents($sFile);
}else{
echo '403';
}
?>

W tym rozwiązaniu, za podjęcie decyzji, czy użytkownik ma prawo pobrać plik, odpowiada funkcja allowFileDownload(). Całość jest oczywista - jeżeli funkcja zwróci true, wysyłamy do przeglądarki zawartość pliku.

Większość z was zauważy pewnie, że powyższy przykład jest cokolwiek niekompletny. Należałoby uzupełnić go o wysyłanie nagłówków HTTP - przedewszystkim Content-type oraz Content-length. Wpis ten ma jednak traktować o czym innym, dlatego pominąłem wszystko co nie jest niezbędne. Kompletne podejście do udostępniania plików z wykorzystaniem PHP jest tematem na oddzielny wpis.

Szybsze rozwiązanie

PHP działające jako moduł Apache udostępnia funkcję virtual(). Funkcja ta wykonuje wewnętrzne żądanie Apache i przekazuje na wyjście jego wynik. Po zmodyfikowaniu powyższego przykładu, uzyskamy:


<?php
if(allowFileDownload($sFile)){
virutal($sFile);
}else{
echo '403';
}
?>

Co zyskujemy?

Przedewszystkim zyskujemy na wydajności, przy wysyłaniu większych plików. Aby porównać wydajność obu rozwiązań, wykorzystałem program ab.exe, o którym pisałem wcześniej. Podczas wykonywania testów, ustawiłem paramety programu na: ilość żądań - 100, równoległość żądań - 3. Testy przeprowadziłem dla 3 plików o różnej wielkości. Oto wyniki:

Rozmiar pliku file_get_contents() virtual()
650 b 88 ms 102 ms
1.15 mb 1241,99 532,97
1.80 mb 1789,07 ms 781,72 ms

Tabela zawiera średnie czasy odpowiedzi serwera. Jak widać, dla większych plików wydajność virtual() jest znacznie większa niż file_get_contents().

Zyskujemy także elastyczność i możliwość wykorzystywania wielu języków server-side w aplikacji. Jak? Należy pamiętać, że żądanie wykonane przez virtual() jest obsługiwane przez Apache. Jeżeli żądanie odnosi się do pliku CGI, to zostanie on wykonany. Dzięki temu możemy włączyć do strony, wynik działania np. skryptu Perla.

Co tracimy?

Przedewszystkim przenośność kodu. Funkcja virtual() jest dostępna tylko, gdy PHP działa jako moduł Apache lub jako moduł NSAPI w serwerach Netscape, iPlanet, SunONE. Odpadają więc wszystkie inne serwery oraz serwery gdzie PHP działa za pośrednictwem CGI.

Ponieważ pliki są udostępnione przez wywołanie żądania Apache, nie można przenieść ich poza drzewo dokumentów serwera. Dochodzi więc konieczność zabezpieczenia katalogu z chronionymi plikami przed dostępem z zewnątrz w taki sposób, aby jednak możnabyło wywołać żądanie z poziomu PHP. W manualu znalazłem rozwiązanie, polegające na odmowie dostępu do katalogu, z wyjątkiem tych żądań, które mają ustawioną zmienną PHP_ALLOW:


<directory katalog_z_plikami>
Order Allow,Deny
Allow from env=PHP_ALLOW
</directory>

W skrypcie PHP, przed wywołaniem funkcji virtual(), ustawiamy zmienną:

<?php
if(allowFileDownload($sFile)){
apache_setenv('PHP_ALLOW', '1');
virutal($sFile);
}else{
echo '403';
}
?>

O aspektach wykorzystania funkcji virtual() możnaby jeszcze conieco napisać, ale jestem pewien, że sięgniesz do manuala. Liczę na to, że wyniki wydajności, które przedstawiłem skłonią Cię do własnych testów. Jeżeli już je wykonasz, mam nadzieję, że się nimi podzielisz. Czekam zresztą na wszystkie uwagi, a nie tylko te, dotyczące wydajności.

Nadszedł 2007 rok

styczeń 1st, 2007

Oby Nam się!


statystyki