SmartHub – pierwszy kod serwerowy

W tym wpisie będzie o postępach prac nad projektem. Tak, wrzuciłem pierwszy kod serwerowy, który można uruchomić na RPI. W tym wpisie będzie o tym co dokładnie zostało zrobione i jak uruchomić projekt.

Prace jakie chciałem najpierw zrobić miały dotyczyć modułu audio. Miał to być prosty formularz, w którym podaje się URL pliku audio i wybiera na jakim urządzeniu ma to być odtworzone. Oczywiście udało mi się to zrobić i formularz wygląda tak:

audio-basic-form

Jednak ważniejsze jest to co jest pod spodem. Więc tak – najpierw rozpocząłem poszukiwania biblioteki audio, która potrafi odtwarzać dźwięki, działa na Linuksie i .NET Core. Nie udało mi się takiej znaleźć, więc stworzyłem issue ma githubie .NET Core. W międzyczasie szukałem biblioteki, która by po prostu działała z Mono. Stwierdziłem, że najwyżej nie będę korzystał z ASP.NET Core. Nie było aż tak źle, ponieważ sprawdziłem za pomocą dyrektywy #if DNX451, że kod uruchamiany w .NET Core z użyciem Mono na linuxie jest to pełny .NET – czyli biblioteki działające z Mono zadziałają z .NET Core.

Znalazłem bibliotekę BASS.NET, która działa z Mono. Jest to wrapper na wieloplatformową bibliotekę BASS stworzoną przez firmę un4seen. Wrapper ten opakowuje metody napisane w C na metody C# za pomocą mechanizmu P/Invoke (Platform Invoke). MIałem problem z jej uruchomieniem – otrzymywałem błąd System.DllNotFoundException: Unable to load DLL 'bass.dll': The specified module could not be found. Nie wiedziałem jak to naprawić – w dokumentacji biblioteki nie było nic na temat jej instalacji, więc zacząłem szukać jakiś przykładów kodu na Githubie. Wtedy znalazłem bibliotekę ManagedBass, która wydała się lepsza od BASS.NET, bo była świeża, miała otwarty kod, jedną wersję na wszystkie platformy (PCL), nierestrykcyjną licencję oraz poza zwykłym, także obiektowe API. Przepisałem więc przykład z jej wykorzystaniem i próbowałem uruchomić. Dostałem prawie taki sam błąd: System.DllNotFoundException: Unable to load DLL 'bass': The specified module could not be found. Teraz mając dostęp do kodu wiedziałem, że wszystko robię dobrze, a jako, że biblioteka była świeża, to znaczyło, że działa z najnowszą wersją Mono. Zacząłem więc szukać jak obsłużyć w Mono plik dll w wersji linuksowej, czyli *.so i natrafiłem na ten wpis w dokumentacji, który ostatecznie zaprowadził mnie do kolejnego wpisu omawiającego mapowanie nazw bibliotek. Dodałem więc potrzebny wpis mapujący w pliku /etc/mono/config i treść błędu zmieniła się odpowiednio (libbass.so zamiast bass). Teraz jak dostawałem taki błąd to miałem pewność, że przyczyną nie jest zła nazwa ładowanej biblioteki tylko zła lokalizacja pliku libbass.so. Wróciłem do instrukcji instalacji i okazuje się, że trzeba zainstalować bibliotekę w folderze /usr/local/lib (np. w sposób opisany tutaj) – nie można tak jak na Windowsie skopiować pliku biblioteki do folderu wynikowego z aplikacją. Po tych zmianach wszystko zadziałało i poprawnie udało się odtworzyć plik mp3 na Raspberry Pi. Oczywiście instalowana była wersja biblioteki BASS dla procesorów ARM.

Teraz jak patrzę na wpis w dokumentacji Mono odnośnie błędu DllNotFoundException, to wygląda na to, że nie musiałem dodawać wpisu w dllmap, gdyż takie podstawowe podmiany nazw biblioteki robi Mono (i pewnie też dlatego na stronie ManagedBass oraz BASS.NET nie było nic na ten temat). W każdym razie bez tego nie miałem pewności jaka jest przyczyna problemu, co po dodaniu wpisu w dllmap pozwoliło mi na wyeliminowanie problemu złej nazwy biblioteki – no bo skoro nazwa była zła to co z tego, że biblioteka byłaby dobrze zainstalowana jak problem i tak by występował.

Teraz, gdy już demo działało można było przejść do tworzenia docelowej struktury zależności i repozytoriów. Biblioteka BASS jest płatna w zastosowaniach komercyjnych, dlatego będzie to jedna z implementacji modułu audio – na razie jedyna, ale docelowo może być ich więcej. W każdym razie podzieliłem to tak, że API (interfejsy) znajduje się w repozytorium głównym projektu: Luma.SmartHub, a implementacja modułu audio w osobnym repozytorium: Luma.SmartHub.Audio.Bass. Podobnie będą zrobione implementacje pozostałych modułów, które będą wykorzystywać zależności inne niż standardowo dostępne w .NET lub gdy będzie to logicznie uzasadnione. Wydzieliłem także warstwę webową jako osobne repozytorium: Luma.SmartHub.Web. Wynikało to głownie z powodu problemów jakie napotkałem – opisałem je w tym wpisie. Jednak takie oddzielenie także wydaje się być sensowne – pozwoli na oddzielenie logiki prezentacji od podstawowych elementów systemu.

Uruchomienie

  1. Ściągasz repozytorium Luma.SmartHub.Web.
  2. Uruchamiasz build.ps1 lub budujesz w Visual Studio 2015 (należy dodać https://ci.appveyor.com/nuget/luma-smarthub oraz https://ci.appveyor.com/nuget/luma-smarthub-audio-bass jako dodatkowe źródła w NuGecie).
  3. Instalujesz bibliotekę BASS (w wersji ARM) na Raspberry Pi za pomocą tej instrukcji.
  4. Wykonujesz dnu publishkopiujesz na Raspberry Pi i uruchamiasz serwer zgodnie z opisem z tego wpisu (kroki 3 i 4).
  5. Odpalasz stronę http://<ip-malinki>:5000/audio, wpisujesz link do pliku mp3 dostępnego w sieci, naciskasz Play i muzyka zaczyna grać.

Podsumowując udało się rozpocząć pracę nad częścią serwerową i modułem audio. Po wstępnych testach okazało się, że można włączyć odtwarzanie kilku piosenek na raz, w tym na różnych urządzeniach. Nie wiem jeszcze jak odpalić jedną piosenkę na kilku kartach dźwiękowych, ale tym zajmę się w najbliższym czasie. Dzięki temu, że biblioteka BASS jest wieloplatformowa, można testować kod zarówno na Windowsie jak i na Linuksie – jedynie wymagana jest instalacja odpowiedniej wersji tej biblioteki w systemie, a po stronie kodu nic się nie zmienia. Uzupełniłem także pliki README w stworzonych repozytoriach dotyczących projektu, co pozwoli na szybkie zapoznanie się z zakresem projektu oraz delikatne rozreklamowanie go – w końcu ta strona jest indeksowana przez wyszukiwarki :-). Przy okazji ostatnich prac zapoznałem się z narzędziami ułatwiającymi prowadzenie projektu open source (m.in. AppVeyor i Gitter) i postaram się w przyszłości napisać co nieco na ich temat.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *