Uruchomienie reklamowej tablicy LED, część III

Najtrudniejsze już zrobione – wiadomo jak zmusić tablicę do wyświetlenia czegokolwiek. Teraz czas na spięcie wszystkiego razem – podczas tego etapu prac okazało się, jak po samym protokole komunikacyjnym można odkryć jak rozwijały się produkty firmy NewWing, jakie obejścia przy ich produkcji stosowano i jaki dług techniczny zaciągnięto. 

Tak wygląda strona internetowa tego potentata

Ostatni odcinek skończył się na udanym wysyłaniu do tablicy zapisanych wcześniej danych. Prace nad pełnym rozgryzieniem protokołu zaczynamy od modyfikacji bajtów w zrzutach i obserwowaniu wyniku – po kilku próbach bez większych problemów rozpracowałem ogólny schemat.

Podział na logiczne bloki

Blok zaznaczony na szaro zawsze pozostawał taki sam – nazwałem go preambułą. Podejrzewam że zawiera podstawowe parametry, takie jak szerokość i wysokość. Niestety brakuje mi możliwości aby to w pełni zweryfikować. 

Blok oznaczony na niebiesko to ustawienia efektów – zmieniając bity w nim sprawiałem że tekst przesuwał się na tablicy w różnych kierunkach lub był animowany w jeden ze sposobów znanych z naszych ulic. Małym smaczkiem było odkrycie parametru mówiącego o długości tekstu – ustawiając go na dużą wartość można przejrzeć historię danych na tablicy.

Blok zielony, żółty i czerwony to dane pojedynczych pikseli. Po ich zmianie zapalają się i gasną pojedyncze diody. Każdy bajt koduje 4 piksele, tylko nieparzyste bity są używane (pozostałe są ignorowane przez tablicę). Możliwe że protokół działa z tablicami dwukolorowymi (parzyste bity sterują pewnie tym drugim kolorem).

Trzy zapalone piksele = A2

Dlaczego więc trzy kolory bloków? To ilustracja bardzo nieeleganckiego rozwiązania problemu z jakim starli się Chińscy inżynierowie, ale żeby go wyjaśnić, przeanalizujmy jak wygląda cała komunikacja z urządzeniem – warto jeszcze przed tym zaznaczyć, jak fizycznie zbudowana jest moja tablica. Ma ona trzy fizyczne segmenty diod o wymiarach 32 ✕ 32 = 1024 diod na segment.

Liczby przed blokami danych (te niepokolorowane) oznaczają ile bajtów w bloku tablica ma przetworzyć. Większość bloków zaczyna się siódemką (nazwijmy je pełnymi), kodują one 28 pikseli. Po nich wysyłany jest jeden blok z czwórką na początku (nazwijmy go uzupełniającym) i tylko cztery bajty z niego tablica przetwarza, pozostałe są ignorowane bez względu na wartość. Daje to razem 16 pikseli. Po wysłaniu takiego bloku uzupełniającego należy odczytać komunikat z tablicy – tak jakby oznaczało to „zatwierdzenie” całego, dużego bloku transmisyjnego.

Mając te dane można policzyć, ile pikseli zawiera jeden blok transmisyjny – drugi i trzeci zawierają po 1024 piksele, czyli tyle co jeden fizyczny segment. Ale przez to że na samym początku został upchnięty jeden bloczek z ustawieniami efektów, bloki transmisyjne nie tylko nie pasują do segmentów tablicy, ale też konieczne staje się wysłanie dodatkowego, małego bloku specjalnego na końcu, z danymi dla tych kilkunastu pozostałych diod.

Być może w pierwszych tablicach, bez żadnych animacji, układ bloków był logiczny, ale kiedy pojawiła się konieczność dodania efektów, dolepiono je na szybko tak, jak było najłatwiej nie przejmując się logiką transmisji.

Tutaj jeszcze tego nie ogarnąłem

Będąc uzbrojonym w te wszystkie informacje można stworzyć skrypt wyświetlający dowolny tekst – ja użyłem do tego Pythona i biblioteki Pillow. Stworzenie w niej monochromatycznego obrazka z tekstem to już kilkulinijkowa bułka z masłem – dużo bardziej złożone było wygenerowanie bloków danych tak, aby wyświetliły się na tablicy zgodnie z założeniem.

No i w końcu działa!

Więcej o Pillow i graficznej części tego zadania w następnej części. Ale to jeszcze nie będzie wszystko – trzeba rozwiązać jeszcze kilka niecodziennych problemów, takich jak znalezienie odpowiednich czcionek. Magiczny dym uciekający z tablicy również się pojawi…

Uruchomienie reklamowej tablicy LED, część II

„Kablem! Ja po prostu wpisywałem tekst i przez kabel byłem połączony” – taką informację usłyszałem od pracownika który z tym chińskim cudem techniki miał doświadczenie. A więc wybrałem się do najbliższego sklepu i kupiłem jedyny dostępny tam kabel, za pomocą którego mogłem nawiązać łączność z tablicą – USB C ↔ USB A. Takimi kablami zwykle podłącza się nowe telefony, ale w swoim laptopie posiadam zarówno złącze USB C jak i popularne A.

Znalezione obrazy dla zapytania usb connector types
Krótka ściąga z wtyczek USB

UWAGA! To, że urządzenie ma port USB nie oznacza że można je bezpiecznie podłączyć do innego sprzętu z portem USB – a szczególnie kiedy jest to wynalazek w oczywisty sposób łamiący standardy USB (kable A ↔ A są z nim niezgodne). Można spalić swój komputer, urządzenie docelowe, albo obydwa na raz. Tak, widziałem takie przypadki i to nawet całkiem niedawno. 

Sam fakt tego, że tablica jest raz hostem USB a raz ma być urządzeniem peryferyjnym i to wszystko na USB 2.0 które oficjalnie nie pozwala na takie harce brzmi bardzo dziwnie. Mimo wszystko zdecydowałem się zaryzykować i świeżo kupionym kablem podłączyłem laptopa do tablicy. Dymu ani płomieni nie było, obydwa urządzenia wciąż działały i nawet odbyła się między nimi jakaś próba komunikacji – ale nie ma co mówić o sukcesie.

Kabel był akurat w porządku

Jeszcze jeden telefon do eksperta i udało mi się zarezerwować wizytę w magazynie w którym spoczywał zarówno komputer używany do sterowania tablicą jak i kabel z którego pomocą przesyłano do niej dane. Pożyczyłem obydwa (jak się okazało, na komputerze był Windows Vista a nie ME) i przyszedł czas na kolejny eksperyment.

Jak się okazało, pożyczony zestaw faktycznie działał i kluczowy był tutaj kabel. Kiedy użyłem go ze swoim laptopem, w dzienniku zobaczyłem wykrycie nowego urządzenia.

Coś tu dalej nie gra

W systemie nie pojawił się jednak żaden nowy port szeregowy. Jak w końcu XYLED przesyła te dane, skoro w każdym oknie tego programu jest coś o portach szeregowych? To nie jest wina systemu, Windows tak jak Linux wykrywa tablicę jako urządzenie HID (takmi są m.in. mysz czy klawiatura). O co tutaj chodzi?

Po skonfigurowaniu odpowiednich uprawnień wine również obsługuje HID i faktycznie, XYLED steruje tablicą bezproblemowo. Problem mam natomiast ja, bo czas goni a ja w życiu swoim nigdy nie programowałem interfejsu USB. Jedną z niewielu rzeczy którą na ten temat wiem, to to że Wireshark kilka lat temu dostał funkcjonalność podsłuchiwania ruchu USB. 

Nie wygląda to najgorzej

Zrzut komunikacji nie wyglądał na przytłaczający – jedyne wiadomości to URB_INTERRUPT, zwykle wychodzące z komputera i co jakiś czas przychodzące z tablicy. W każdej takiej wiadomości zawsze równo 8 bajtów. Łącznie 246 wiadomości – to daje całkiem „ogarnialną” liczbę danych.

Skoro mamy już taki zrzut, pierwszy krok to napisanie programu który podszyje się pod XYLED i odtworzy poprawnie komunikację z tablicą, dając ten sam efekt co oryginał. Aby się do tego zabrać, trzeba ze zrzutu wyłuskać same tylko dane, bez nagłówków USB. Żeby zrobić to szybko, zdecydowałem się skorzystać ze swojej ulubionej metody prototypowania – programu ipython, bardzo interaktywnej nakładki na interpreter Pythona, która błyskawicznie pozwoliła mi stworzyć skrypt który wyłuska odpowiednie bajty z użyciem biblioteki scapy.

Raz dwa i gotowe

Podsłuchałem komunikację z kilkoma bardzo prostymi przykładami – literami A, B, C, kropką i przecinkiem. Mając zrzuty komunikacji przefiltrowane przez powyższy program, można spróbować gołym okiem stwierdzić co mniej więcej wysyłane jest do tablicy.

Na przykładach kropki (składa się tylko z jednego piksela) i B widać że początek komunikacji jest taki sam i że zgodnie ze zdrowym rozsądkiem dane przesyłane są jako bitmapa. W analizie można pójść o krok dalej i zaprzęgając do współpracy narzędzie xxd przekonwertować pliki binarne na tekstowe, które będzie można łatwo porównać.

Kropka kontra przecinek

Kropka i przecinek różnią się dokładnie jednym bajtem, a więc wiadomo że w protokole nie ma sum kontrolnych, długość komunikacji jest stała (przynajmniej dla krótkich tekstów) i początek komunikacji jest zawsze taki sam. Nic tylko ją odtwarzać! Ale jak?

Na szybko znaleziona biblioteka hidapi zdaje się dawać wszystko czego potrzeba. Potrafi wyliczać urządzenia i łączyć się z nimi za pomocą identyfikatora producenta i urządzenia (zresztą to może być powód dla którego Chińczycy zdecydowali się wybrać HID – nie ma problemu z szukaniem portu, który nęka urządzenia korzystające z portów szeregowych). Biblioteka pozwala też na zapis i odczyt z urządzeń.

Po kilku minutach miałem gotowy program, który w paczkach po 8 bajtów wysyłał dane do tablicy. Z wielkimi nadziejami uruchomiłem go i… cała tablica zgasła a po chwili program zawisł. Nie zamykając go, zacząłem szukać błędu. I wtedy, po kilku minutach kątem oka zobaczyłem krwistoczerwoną łunę.

A

Podsłuch komunikacji nie wykazał różnic w danych wysyłanych, ale wciąż pozostawała jedna ważna różnica – nie próbowałem niczego z tablicy czytać. Policzyłem wiadomości i na sztywno zaszyłem w programie odczyt danych w tych samych momentach co XYLED. 

Okazało się to kluczem do sukcesu – program przesłał dane błyskawicznie i wynik był zgodny z oczekiwaniami

B Bez problemów

Najtrudniejsze wydawało się gotowe. Teraz zostało już tylko ostateczne rozpracowanie protokołu, wygenerowanie odpowiednich bitmap i podłączenie do mediów społecznościowych. I o tym wszystkim będzie w dalszych częściach (w których też będzie kilka ciekawych przygód).

Uruchomienie reklamowej tablicy LED, część I

Kolejowe tablice paletowe leżą od wielu miesięcy w magazynie i być może niedługo znów zostaną wprawione w ruch – dobrą rozgrzewką przed tym projektem jest zadanie którego podjąłem się kilka dni temu, czyli opracowania mechanizmu sterowania reklamową tablicą LED.

Zdjęcie poglądowe, tablica z oferty sklepu Soled

Zasady podobne co ostatnio – projekt zakłada automatyczne wyświetlanie na tablicy wiadomości z mediów społecznościowych i trzeba go wykonać maksymalnie w kilkanaście dni. Problem: Zgodnie z informacjami obsługi, tablicę można oficjalnie obsługiwać tylko z użyciem specjalnego programu, który działa jedynie pod Windowsem ME. Rozpracowanie sterowania taką tablicą brzmi jak doskonała zabawa, a więc zaczynamy!

Na samym początku otrzymałem samą tablicę i archiwum z programem do jej obsługi. Jedyną formą kontaktu z tablicą (oprócz kabla zasilającego) było gniazdo USB. Na liście plików widać pliki sterownika do konwertera USB↔UART CH340 – bardzo popularnego i taniego modułu, wszechobecnego w chińskich klonach Arduino. Pierwsza teoria  – tablicą steruje się przez właśnie taki moduł – Windows faktycznie potrzebuje do niego dodatkowego sterownika, więc może co tłumaczyłoby obawy pracownika dotyczące systemu. 

Lista plików mających umożliwić sterowanie chińskim wynalazkiem

Wśród plików jest też instrukcja i od jej lektury zacząłem zabawę z urządzeniem. Instrukcja jest pisana chińskim dialektem angielskiego i nie wiadomo do końca od czego właściwie jest – czy opisuje jak działa sam sterownik do diod, czy jest w ogóle od innej tablicy – moja była jednobarwna, podczas gdy w opisie jest coś o 64 tysiącach kolorów. Jedyne co miało jakikolwiek związek z moim urządzeniem, to opis zapisywania stworzonej w programie XYLED animacji do pliku który to później można za pomocą pamięci USB załadować na urządzenie.

+5V elektronów

5 minut i 20zł później miałem już dysk i spróbowałem uruchomić program (ambitnie! – z użyciem wine). Okazało się wtedy, że brakuje mi jeszcze jednego elementu układanki – tajemniczej biblioteki BridgeMini.dll. Problem był trudniejszy niż by się wydawało – plik ten był bardzo trudny do znalezienia w morzu serwisów z „brakującymi plikami DLL” (tych kilka prawdziwych nie posiadało w zbiorach tej biblioteki, a dla reszty nie chciałem uruchamiać maszyny wirtualnej). Uratowała mnie podstawowa znajomość języka rosyjskiego – dzięki niej mogłem pobrać właściwy plik ze znalezionego rosyjskiego forum i przeczytać do czego właściwie on służy (kolejny sterownik USB↔UART, niewiadomo dlaczego wymagany do uruchomienia).

Po dodaniu brakującego pliku program w końcu się uruchomił! Powitało mnie archaicznie wyglądające okno z wieloma guzikami i najważniejszym – polem do wpisywania tekstu. Na chwilę wstąpił we mnie duch młodego polskiego kapitalisty będącego o krok od wielkiej chwili – zareklamowania całemu światu swojego przedsiębiorstwa wielobranżowego oferującego absurdalną liczbę usług. Program ma całkiem sporo opcji, ale zanim wszystkie zostaną przetestowane, spróbujmy cokolwiek w ogóle wyświetlić.

Okazało się to jednak mocno nietrywialne – zgodnie z instrukcją, po skomponowaniu swojego programu artystycznego (XYLED pozwala dodać wiele odmiennie skonfigurowanych tekstów, grafiki i aktualną godzinę) za pomocą guzika U-Disk (?) mogę zapisać plik na pamięci USB (program sam je wykrywa i nie pozwala zapisać pliku gdzie indziej). Mam do wyboru dwie opcje których nazwy niewiele mówią i dodatkowo jedna z nich jest chroniona hasłem – brzmi jak typowa przygoda z chińskim oprogramowaniem do wewnętrznego użytku. Po kliknięciu „Save” Plik faktycznie powstaje na dysku, nie czekając długo wkładam go do portu tablicy. I… nic, absolutnie nic się nie dzieje.

Podaję hasło – 168

Eksploracja okien programu zanosi mnie do (chronionych oczywiście możliwym do znalezienia w internecie hasłem) ustawień, w których można wybrać setki opcji. O ile szerokość i wysokość tablicy jestem w stanie poznać licząc diody, to reszta wygląda na bardzo niskopoziomowe ustawienia sterownika i właściwie na poziomie takiego programu nie powinna w ogóle istnieć. Nie mając żadnego innego pomysłu zdecydowałem po kolei testować elementy z listy i sprawdzać, czy tablica zareaguje na moje próby. No i w końcu, po około dwudziestu podejściach, diody przemówiły.

Nie do końca o to chodziło, ale zawsze coś

W mojej głowie już rodziło się pomysł, jak rozwiązać automatyczne sterowanie – stary telefon z Androidem mógłby być zasilany przez USB i jednocześnie symulować dysk USB kiedy trzeba by przeprogramować tablicę. Niestety, nie udało mi się znaleźć działających ustawień, a co więcej – te kombinacje które wcześniej działały, po jakimś czasie nie robiły żadnego wrażenia na tablicy. 

Pozostało mi czekać, aż będę mógł porozmawiać z osobą która tym cudem kiedyś sterowała, ale o tym będzie już w następnej części.