Pokazywanie postów oznaczonych etykietą technikalia. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą technikalia. Pokaż wszystkie posty

2010/05/22

Windows Mobile 6.5 vs Internet i MMS

Jak to zwykle bywa, po wymianie oprogramowania w aparacie tekefonicznym z którego korzystam straciłem możliwość wysyłania MMS'ów. Okazało się, że przywrócenie tej funkcjonalności nie należy do rzeczy prostych. Zwłaszcza, gdy okazało się, że owe oprogramowanie nie ma Playa na liście operatorów i co więcej system komórki nie akceptuje smsów z konfiguracją. Musiałem, więc wszystkich zmian dokonać ręcznie. Nie było to wcale takie proste, gdyż wymagało zmian nie w jednym a w dwóch miejscach, które co prawda wydają się dość intuicyjne, ale są pomimo tego mało wygodne. Niestety windows na PC przyswyczaił mnie do istnienia różnych kreatorów a tu najzwyczajniej w świecie kreator nie bangla. Ale do rzeczy.

Konfigurujemy połączenie "Play Internet" ( Start/ Settings/ Connections/ Connections)
APN:
internet

Ustawiamy je jako podstawowe w dziale Advanced / Selected Networks

W przypadku MMS musimy jak już wcześniej konfiguracji dokonać w dwóch miejscach

Konfigurujemy połączenie "Play MMS" ( Start/ Settings/ Connections/ Connections )
APN:
mms

W programie do wysyłania SMS/MMS (MMS Options)
Gateway:
10.10.25.5
Port: 8080
Server address: http://10.10.28.164/mms/wapenc
Connect via: "Play MMS"

i Voila. Działa :]

Rafał Prasał.

2010/05/14

SharpNapiProjekt

Całkiem niedawno, to znaczy w dniu dzisiejszym ukończyłem aplikację do pobierania napisów z NapiProjekt.pl. Napisana ona została z użyciem platformy .NET 4.0 w języku C# i w przeciwieństwie do pierwowzoru nie otwiera wielu okien przy pobieraniu napisów do więcej niż jednego filmu. Jedno okno w zupełności jej wystarcza. Jeśli chodzi o funkcjonalność to jest ona na podstawowym poziomie, ale w zupełności powinna wystarczyć przy normalnym użytkowaniu tzn. pobieraniu napisów :). Odpowiednie odnośniki do pobrania znajdują się niżej.



Jak Zainstalować

  1. Rozpakuj SharpNapiProjekt.zip np. do c:\Program files\
  2. Uruchom jako Administrator c:\Program files\SharpNapiProjekt\SharpNapiProjekt.exe (Prawym na programie i 'Uruchom jako Administrator')
  3. Kliknij "Install ShellMenu"

Jak Odinstalować
  1. Uruchom jako Administrator c:\Program files\SharpNapiProjekt\SharpNapiProjekt.exe
  2. Kliknij na "Remove ShellMenu"
  3. Skasuj c:\Program files\SharpNapiProjekt

Jak Używać
  1. Po zainstalowaniu ShellMenu
  2. Klikasz prawym przyciskiem myszy na pliku lub plikach z filmami
  3. Klikasz lewym przyciskiem myszy na "Get Subtitles"

Aplikacja zostaje udostępnione tak jak jest. Autor nie ponosi żadnej odpowiedzialności za straty wynikłe z używania tej aplikacji.

Pobieranie

Rafał Prasał

2010/03/20

Zylion procent normy

Każdy z nas, ludzi zajmujących się między innymi pisaniem zapytań SQL trafia na przypadki, które w jakiś sposób są wyzwaniem. Dla jednych mogą to być miliony rekordów w płaskiej tabeli, dla innych, no cóż tabela przestaje być płaska a jej pola zaczynają być indeksami do innych tabel.

W mojej praktyce zawodowej, miałem do czynienia z różnymi przypadkami, które w mniejszym, lub większym stopniu miały znaczący wpływ na obniżanie wydajności serwisów, których dotyczyły. Błędy lub niedopatrzenia jakie popełniono, mogły zdarzyć się każdemu i pewnie przy tworzeniu rozwiązań na "szybko" przytrafiają się częściej niż możemy sobie to wyobrazić.

Łączenie się w trakcie generowania strony do zewnętrznych serwisów

Początkowo wszystko wydaje się fajne, bo działa, jednakże w przypadku styku z użytkownikami
a. niepotrzebnie zapychamy sobie łącze
b. w przypadku padu połączenia z zewnętrznym serwisem, co może zdarzyć się np. jak domena przestanie istnieć, nasz serwis klasycznie dostanie DDOS.

Jak się tego ustrzec? Rozwiązanie wydaje się prostsze niż mogłoby się wydawać. Otóż można np przy pomocy CRONa zrzucać interesującą nas informację zewnętrznego serwisu do plików tymczasowych na naszym serwerze i to właśnie wykorzystywać w naszych skryptach

Karkołomne zapytania wykonywane przy każdym kliknięciu
Przypuśćmy, że chcemy w naszym serwisie pokazać dziesięć losowych spośród stu najnowsze wiadomości, które z kolei mogą znajdować się na forach, obrazkach, blogach lub w samym naszym serwisie. Przypuśćmy też, że treści generowanych przez użytkowników jest sporo powiedzmy 1000-100000 elementów dziennie a ilość wejść przez użytkowniów na nasz serwis to milion miesięcznie. Żeby stworzyć interesujący nas widok musimy wykonać, kilka zapytań, albo jedno i użyć konstrukcji union, gdyż dane będą pochodziły z kilku tabel. Genralnie jak się to wszystko policzy to masakra. W każdym razie dobrą praktyką jest użycie cache'y, ale teraz jak się z tematem zmierzyć? prawdę mówiąc istnieją 2 rozwiązania

1. Dane w czasie rzeczywistym
Dla każdej interesującej nas tabeli tworzymy trigger "after insert", który będzie ją umieszczał w tabeli cache_100 oraz dbał o to, żeby ilość elementów nie przekraczała 100. Praktyka pokazuje, że przy takiej ilości danych indeksy w tabeli cache_100 są zbędne i obniżałyby wydajność. Jednakże nawet w przedstawionym przeze mnie przypadek, może się nie sprawdzić, to znaczy wtedy, gdy ilość generowanych treści przez użytkowników będzie o rząd albo o dwa rzędy większa.

2. Dane opóźnione o jakiś czas
Innym podejściem do tematu jest wykonanie owego karkołomnego zapytania raz na jakiś czas np 5min-10min(CRON)i umieszczenie wyników w tabeli cache_100. Użytkownikowi i tak jakoś specjalnie to nie będzie przeszkadzało a my zyskamy na tym, że nawet znacznie zwiększony ruch nie zabije nam usługi.

Miliony rekordów w tabeli o wielu dowiązaniach
W sumie jest to najciekawszy przypadek jaki do tej pory miałem. Baza danych była dość skomplikowana, dowiązania wielokrotne w liczbie 15. Ogólnie sam widok schematu przyprawiał o zawrót głowy. Nie mówię, że to coś złego, po prostu takie było odzwierciedlenie nieabstrakcyjnych urządzeń znajdujących się w terenie. Jeśli doliczyć do tego ponad milion a nawet do dwóch milionów rekordów rocznie i wyniki generowane w czasie rzeczywistym filtrowane po subdevice_id i czasie to już w ogóle dech w piersiach zapiera a na usta cisną się niecenzuralne słowa. Pominę już fakt, że jeśli urządzenie zwariuje to może wysłać 10k rekordów w przeciągu jednej godziny a czasami nawet i więcej. Zapytanie takie jak poniżej, nie wchodziło w grę, choćby ze względu na to, że mogłoby się wykonywać nawet do 5-24h, bo inicjalne ustawienie pól cache'ujących trwało bagatela 1.5h.
Select * from msgs left join ... where .... order by ... limit ...;
Użyłem triggerów, które zadbały o to, żeby baza sama "pilnowała" wariantów i przynajmniej częściowo cache'owała wyniki podzapytań z dowiązań.
msgs.subdevice_id = (select device_id from devices where devices.supdevice_id = msgs.device_id and devices.subdevice = msgs.subdevice))
Czas wykonywania skrócił się do 30-60 sekund. Gdyby ten wynik zadowalał mnie i klienta to pewnie bym i na tym poprzestał, ale dla nas obojga było to niewystarczające.

Na odsiecz przybyło podzapytanie użyte w polu FROM. To zapytanie nie było specjalnie trudne ot, po prostu służyło do zawężania wyników po subdevice_id i dacie. Czyli w efekcie końcowym powstał taki twór
$x= "Select * from msgs where subdevice_id in ( $subdevices ) and rtime > $start and rtime < $koniec order by rtime desc limit 101;";
a to z kolei zostało umieszczone w polu FROM, Czyli
$sql = "Select * from ( $x ) left join ..."
Dla niektórych to, co zostało zrobione tutaj to kombinacja norweska z alpejską w jednej, ale tak naprawdę jest to bardzo proste do zrozumienia. Otóż w powyższym rozwiązaniu został wykorzystany fakt, iż zapytania na zindeksowanej "płaskiej" tabeli wykonują się o niebo szybciej niż zapytania, w których występują złączenia z innymi tabelami. Jest tak między innymi dlatego, że najpierw tworzone są wiersze wynikowe czyli między innymi rozwiązywanie dowiązań a dopiero potem następuje ich zawężanie. Zatem "Superszybkie" zapytanie zawężające liczbę wyników do 101 znacznie zmniejszyło ilość rozwiązywanych dowiązań z innymi tabelami, przez co baza danych w końcu zaczęła oddychać.

Możecie wierzyć lub nie, ale to rozwiązanie skróciło czas wykonywania zapytania do 100-300ms czyli w porównaniu z 5-24h wychodzi od 6M do 28.8M%, co wydaje się być wynikiem, co najmniej zadowalającym :].

Rafał Prasał.

2010/02/04

Ja vs JeromeDL

Wiele rzeczy zdarzyło mi się już mi się w moim krótkim życiu instalować, ale to przerosło moje wszelkie wyobrażenia. Otóż w ostatnim okresie miałem za zadanie zainstalować bibliotekę cyfrową pisaną między innymi na PG JeromeDL. Na stronie projektu znajdują się do pobrania jej różne wersje, które z jakichś nieznanych mi bliżej powodów zostały uznane za stabilne.

Kilka nie współpracowało z Javą 1.5 a kilka jedyne co po instalacji i próbie uruchomienia zrobiło, to rzuciło w logach wyjątkiem i zakończyło pracę. Jedyna wersja jaką udało sięuruchomić była usb-stick, ale tu też nie ma co wpadać w euforię ponieważ wersja ta nie działała w sposób poprawny uniemożliwiając np logowanie się w serwisie. Nie muszę dodawać, że bez zalogowania się w serwisie nic nie można zrobić.

Na szczęście jeden z byłych developerów JeromeDL udostępnił mi wersję rozwojową, która już umożliwiła zalogowanie się do serwisu. Tutaj też opadłby mi witki, gdy nie można było dodawać plików JPG. Nie muszę mówić, że jest to podstawowa funkcjonalność!. Dołączone aplety javy do importu jpg u mnie się wyświetliły, a u moich kolegów i koleżanek już nie. To, że się wyświetliły to pikuś, ale żadna zaoferowana przez nie funkcjonalność nie zadziałała w sposób poprawny. Na szczęście udało się dodać pliki PDF.

Pomijam już fakt, że projekt ten powstaje od x lat i był rozwijany przez wielu programistów, ale... po prostu szkoda słów... Wydaje mi się, że jednak można było to zrobić znacznie szybciej i znacznie lepiej i przede wszystkim nie używając JSP.

Jeśli ktoś kiedyś będzie rozważał użycie tego jakimś profesjonalnym rozwiązaniu to szczerze odradzam. Może jak wyjdzie, o ile wyjdzie wersja 3.0 to gra będzie warta świeczki, ale na teraz najzwyczajniej w świecie nie warto się w to pchać.

Rafał Prasał.

2010/01/14

Ja vs QT + Eclipse + MinGW

Przez uczelnię zmuszony zostałem z porzucenia znanego i lubionego przeze mnie Visual C# 2008 Express z Windows.Forms na rzecz Eclipse + QT4 + MinGW. Pomyślałem, hmm: co może być w używaniu tego trudnego? Skoro wszystkie te elementy istnieją na rynku programistycznym już od paru lat... Nic bardziej mylnego. Zaczynajmy...

Instalacja
Wydawałoby się, że to najprostsza rzecz, zainstalować edytor, kompilator, SDK a na koniec coś, co zintegruje nam SDK z edytorem. Sama instalacja jest trywialna, gdy już ma się wszystkie dostępne elementy, ale ich znalezienie. O ile Eclipse, QT-Framework. QT-Eclipse-Integrator dostępne są wprost o tyle MinGW4.4.0 to inna para kaloszy. Na szczęście TrollTech udostępnił właściwą wersję MinGW na swoim serwerze FTP. Szkoda tylko, że nie dorzucili tego adresu do miejsca pobierania samego Frameworka.

Użyteczne adresy

Pierwszy projekt
Po zainstalowaniu wszystkiego, Eclipse się uruchomił, wybrałem katalog przestrzeni roboczej i przystąpiłem do pracy. Nowy projekt -> QT Gui, podałem nazwę i wygenerowało mi podstawę, którą później miałem rozwijać. No właśnie. W QT wszystko robi się inaczej niż w .NET. Eclipse udało mi się jeszcze jakoś okiełznać, ale... Otóż QT-Designer zintegrowany z Eclipse pozostawił nieco do życzenia. Otóż to, co znałem z VS2005/2008, że klikamy na obiekt dwukrotnie i generowane jest zdarzenie onclick() tutaj po prostu nie istnieje. Co więcej, edycja "Sygnałów" nie umożliwia wybrania własnej metody obsługi zdarzenia. Okazuje się, że w QT takie rzeczy trzeba napisać ręcznie.

W klasie głównej mojego projektu (plik [projekt].h) zmuszony byłem dodać
class [projekt]{
...
public slots:
void on_[element]_[sygnał]();
...
}
Implementację natomiast umieściłem w pliku [projekt].cpp
...
void [projekt]::on_[element]_[sygnał]()
{
// do Something
}
...
Jeśli myślicie, że reszta poszła już z marszu to, jesteście w błędzie... ale to wynikało raczej z mojej awersji do języka C++, który do najwygodniejszych języków niestety nie należy. Konstrukcja cos.cos()->cos().cos to jednak nie jest to, co tygryski lubią najbardziej.


Wnioski
QT, to bardzo złożony ale jednocześnie dobrze przemyślany framework, który z wersji na wersję staje się prostszy w wykorzystywaniu. Problemem są narzędzia, które mogłyby jednak nieco tę współpracę ułatwiać. Może kiedyś dotrą do poziomu jaki osiągnął MS tworząc VS2005/2008 a kiedy to się stanie to na pewno będzie częściej wybierane jako środowisko wytwarzania aplikacji.

2009/12/21

.NET/ GPS/ SerialPort i takie tam

W dzisiejszych czasach wielu z nas posiada w swoich zasobach sprzętowych GPS'a. Czy to na USB, czy BlueTooth czy też w końcu port szeregowy. Wydawałoby się, że jest to urządzenie tak magiczne, że tylko niektórym uda się je poprawnie obsłużyć. Okazuje się jednak, że w rzeczywistości, nie jest to jakieś specjalnie trudne. GPS, jest widoczny w systemie jako port szeregowy, który inicjujemy następującymi parametrami
  • prędkość: 9600 baud
  • parzystość: 1 bit
  • dane: 8 bitów
W .NET można to swobodnie zrobić przy pomocy obiektu SerialPort. Jako, że komunikaty GPS(NMEA) przychodzą do nas w liniach bardzo pomocna będzie metoda ReadLine(). Komunikaty przychodzą w sposób ciągły, więc funkcję odczytującą je należałoby zamknąć w innym wątku.

Tu właśnie zaczynają się schody, gdyż
  • Do odpalania metod obiektów operujących w innym wątku służy Invoke().
Najzwyczajniej w świecie musimy do obiektu wątku przekazać jako parametr obiekt, który będzie aktualizował dane na ekranie.
  • Obiekt SerialPort potrafi rzucić wyjątkiem podczas próby odczytu, w trakcie zamykania z innego wątku. Jest to ten rodzaj wyjątku, którego nie da się w sposób łatwy przechwycić.
Aby pozbyć tego niemiłego akcentu należy wykonać kombinację alpejską i umieścić odczyt danych z portu szeregowego w bloku finally, gdzie musimy przechwytywać wyjątek pochodzący właśnie z SerialPort.

I tym oto sposobem po kilku godzinkach przeglądania stron i przeszukiwania internetu udało mi się popełnić prostą aplikację, która wskazuje na GoogleMaps, gdzie się aktualnie znajdujemy.

Zapraszam do pobrania i lektury kodu aplikacji

Zastrzegam, że nie ponoszę żadnej odpowiedzialności za straty powstałe w wyniku wykorzystania stworznej przeze mnie aplikacji . Taki Lajf :>

Rafał Prasał

2009/10/20

libpam-mysql i joomla 1.5

W życiu każdego z nas, zarządcy serwera, pojawiają się czasem takie chwile, kiedy to co oferuje nam oprogramowanie już wytworzone przez kogoś, po prostu nie wystarcza. W dzisiejszym odcinku na warsztat poszło libpam-mysql, gdzie niestety zabrakło mi funkcjonalności umożliwiającej zintegrowanie haseł użytkowników z joomla 1.5. Rozwiązanie okazało się o tyle proste, że hasła są hashowane przy pomocy md5 z saltem, który to znajduje się wraz z hashem hasła w kolumnie jos_users.password jako "passwd_md5:salt". Innymi słowy wystarczyło obliczyć md5(passwd+salt) i porównać to z passwd_md5. Nie było to jednak tak trywialne jak mogłoby się wydawać, ale udało się. Odpowiedni patch zgodny z libpam-mysql-0.7RC1 został przeze mnie zgłoszony i znajduje się tutaj. Aby skorzystać z tego mechanizmu należy ustawić crypt=5.

Zastrzegam, że nie ponoszę żadnej odpowiedzialności za straty powstałe w wyniku wykorzystania stworzonej przeze mnie poprawki. Taki Lajf :>

Rafał Prasał