Nowoczesne aplikacje wymagają rozwiązań zapewniających łatwość ich utrzymania oraz skalowania. Takie możliwości może nam pomóc uzyskać Magazyn Zdarzeń. W artykule tym opowiem co to takiego, jakie korzyści nam daje i jak możemy go zastosować.

Artykuły o programowaniu, poruszające tematy typowo techniczne, nowości ze świata developmentu, sposoby implementacji różnych funkcjonalności i integracji bibliotek oraz zewnętrznych serwisów.
Od czasu do czasu robię sobie mały hackaton, polegający na napisaniu jakiejś prostej gry. Na blogu opisywałem już Catapult Moonshot napisany na GameJam a także grę w kółko i krzyżyk w widoku izometrycznym. Tym razem wziąłem na warsztat klasyczną grę Saper, w oryginale zwaną Minesweeper. Jako punkt wyjścia obrałem podobne rozwiązanie jak w przypadku gry w kółko i krzyżyk, czyli język C++, bibliotekę SDL2 oraz widok izometryczny.
W ostatnich dniach podjąłem się małego projektu, który dłuższy od jakiegoś czasu już chodził mi po głowie.
Celem było wygenerowanie mapy z zaznaczonymi wszystkimi ścieżkami jakie przemierzyłem rowerem mając włączony gps-tracker.
Do dyspozycji miałem mieszankę plików .gpx i .tcx wyeksportowanych z aplikacji Endomondo oraz Strava.
Rezultat prezentuje się jak na poniższym obrazku, a jak tego dokonałem, czytajcie poniżej.
W magazynie Programista, numer 5/2020 (92) ukazał się artykuł Gra w Życie: podróż w nieznane z Johnem Conwayem, autor: Rafał Kocisz, który zainspirował mnie aby pobawić się automatami komórkowymi. Co to takiego? Już wyjaśniam.
Gra w życie to gra zero-osobowa, czyli nie wymaga sterowania. Idea jest dość prosta: mamy określoną planszę i na niej umieszczone komórki, którą mogą być żywe lub martwe, np.:
Białe pola to żywe komórki, czarne to martwe komórki.
W każdym cyklu programu sprawdzane są dla każdej z komórek następujące warunki:
Do implementacji użyłem języka Python i biblioteki PyGame, zestaw ten pozwolił mi w bardzo krótkim czasie zacząć zabawę z automatami komórkowymi.
Jak zbudować aplikację Ionic przy pomocy Ionic Hub
Tworząc aplikację w Ionicu spotykamy się z problemem zbudowania paczki apk dla Androida oraz ipa dla iOS. Sposobów na to jest kilka, załóżmy że pracujemy na komputerze z systemem linux, gdzie nie mamy możliwości zainstalowania XCode. Do zbudowania aplikacji możemy użyć narzędzia dostarczanego przez twórców Ionica i nazwanego Appflow, jest ono dostępne pod adresem ionicframework.com (stronę tą będziemy dalej nazywać Ionic Hub). Wersja “Starter” narzędzia Appflow jest darmowa, natomiast z cenami innych wersji można się zapoznać na stronie https://ionicframework.com/pricing#appflow.
Pierwsze co musimy zrobić to dodać naszą aplikację na stronie https://dashboard.ionicframework.com/personal/apps, po kliknięciu “Add app” mamy dwie możliwości:
W pierwszym przypadku należy jedynie podać nazwę aplikacji, w drugim otrzymamy instrukcję którą należy wykonać aby powiązać istniejącą aplikację. Kiedy już nasza aplikacja jest dodana, pojawi nam się jej Dashboard na którym klikamy “Build a Native Binary”.
Po kliknięciu, pojawi się pytanie:
Odpowiedź zależy od tego co wybraliśmy w pierwszym roku: nową aplikację czy istniejącą. Dla potrzeb tego artykułu wybieram “No, show me how”.
Następne pytanie dotyczy klienta Ionic CLI
Raz jeszcze wybieram “No, show me how”. Oczywiście klienta instalujemy tylko raz, więc jeśli wcześniej już go zainstalowałeś, możesz wybrać “Yes”.
Podążając za instrukcjami które pojawią się na stronie wykonujemy kolejno polecenia:
npm install -g ionic – zainstaluje nam to zestaw konsolowych narzędzi Ionica
ionic start myApp tabs – utworzy nam to nowy projekt Ionic. Ważne żeby uruchomić to w odpowiednim katalogu, w którym chcemy mieć aplikację. Jeśli chcemy utworzyć zupełnie pustą aplikację możemy słowo “tabs” zamienić na “blank”. Po wykonaniu polecenia zostaną pobrane potrzebne biblioteki, po jego zakończeniu możemy przetestować naszą aplikację w przeglądarce, aby to zrobić należy przejść do nowo-utworzonego katalogu myApp i wykonać polecenie:
ionic serve
Nasza aplikacja działa już w przeglądarce, możemy więc zakończyć proces `ionic serve` przy pomocy CTRL+C i przejść dalej.
Następne polecenie należy wykonać niezależnie czy właśnie stworzyliśmy nowy projekt czy też chcemy zbudować istniejący:
ionic link
Po wykonaniu polecenia, w konsoli pojawi się kilka pytań:
? What would you like to do? (Use arrow keys)
❯ Link an existing app on Ionic Appflow
Create a new app on Ionic Appflow
Utworzyliśmy już wcześniej aplikację na stronie Ionic Hub, więc wybieramy pierwszą odpowiedź. Następnie otrzymamy listę aplikacji do wyboru, wybieramy tą którą wcześniej utworzyliśmy. Następnie pada pytanie:
? Which git host would you like to use? (Use arrow keys)
GitHub
❯ Ionic Appflow
Ja wybrałem Ionic Appflow. Na koniec otrzymujemy informacje:
> ionic config set id „acfa23d5” –json
[OK] id set to „acfa23d5”!
> ionic git remote
> git remote add ionic git@git.ionicjs.com:polcode/jktest.git
[OK] Added remote ionic.
[OK] Project linked with app acfa23d5!
Od tej pory możemy pushować commity aplikacji do Ionic Hub przy pomocy polecenia:
git push ionic – przy pierwszym uruchomieniu tego polecenia należy podać nazwę brancha: `git push ionic master`, później już wystarczy samo git push ionic.
Co ważne, jeśli nasza aplikacja ma już skonfigurowane repozytorium git, nadal możemy do niego pushować poleceniem `git push`.
Jeśli spushowaliśmy naszą aplikację, powinniśmy zobaczyć commit w sekcji “Commits” w Ionic Hub:
Teraz przejdźmy do sekcji “Deploy” gdzie czeka na nas taki ekran:
Możemy kliknąć “Create your first build” aby stworzyć build ręcznie, ale dużo lepszym rozwiązaniem jest automatyzacja, aby ją skonfigurować przejdź do sekcji “Automate” w menu Ionic Hub:
Kliknij “Create your first Automation”, zobaczysz formularz:
W polu “Name” możesz wpisać dowolną wybraną przez Ciebie nazwę, np. MyAutomation, w polu “Git Branch” podaj “master” (lub inny branch jeśli chcesz), pozostałe pola zostaw bez zmian i kliknij “Create”. Od tej pory po każdym wysłaniu zmian to Ionic Hub (poleceniem git push ionic) build wykona się automatycznie. Dla przykładu utworzyłem plik README.md i wysłałem commit do Ionic Hub, teraz w sekcji Deploy -> Builds widzę że aplikacja się buduje:
Klikając numer w kolumnie “BUILD” możemy zobaczyć szczegóły procesu budowania:
Strona ta pokazuje na bieżąco szczegółowe logi, więc w razie problemów mamy możliwość sprawdzić co się dzieje, na przykład mój build się nie wykonał gdyż nie zainstalowałem Capacitor/Cordova:
Naprawiłem błąd dodając Cordova do projektu:
ionic cordova platform
Przy okazji dodałem też platformy Android i iOS
ionic cordova platform add android ionic cordova platform add ios
Następnie raz jeszcze wysyłam moje zmiany do Ionic Hub i po chwili widzę pomyślnie wykonany build:
Mała uwaga: Strona “Web builds” czasami nie odświeża się automatycznie, więc jeśli widzimy że nasz build jest długo “in progress” warto spróbować odświeżyć stronę.
Identyfikator aplikacji
Istotną kwestią jest ustalenie identyfikatora naszej aplikacji, ustawiamy go w pliku config.xml w atrybucie “id” tagu “<widget>”, domyślnie jest to “io.ionic.starter” i należy to zmienić na wymyślony przez nas unikalny identyfikator aplikacji.
Standardem jest używanie notacji domenowej z odwrotną kolejnością (reverse domain name notation), np. com.mydomain.myapp. Ważne jest, żeby identyfikator zawierał tylko litery, cyfry i kropki, ponieważ inne znaki mogą powodować problemy przy dystrybucji aplikacji.
Certyfikaty
Następnym krokiem jest utworzenie paczki dla Android/iOS, ale zanim będzie to możliwe musimy utworzyć plik keystore, certyfikat i plik .mobileprovision.
Na początek utworzymy klucze i certyfikaty deweloperskie.
Android
W przypadku Androida sprowadza się to do wygenerowania keystore poleceniem:
keytool -genkey -v -keystore MY-RELEASE-KEY.keystore -alias MY_ALIAS_NAME -keyalg RSA -keysize 2048 -validity 10000
W miejsce MY-RELEASE-KEY i MY_ALIAS_NAME należy wpisać nazwę naszej aplikacji, np. Myapp. Polecenie to należy wykonać w katalogu gdzie chcemy przechowywać nasze klucze, powinien to być katalog poza katalogiem projektu, warto również trzymać kopię kluczy, ponieważ po ich utraceniu nie będzie możliwości odzyskania!
Kolejną istotną rzeczą jest podanie hasła dla keystore, zostaniemy o nie zapytani po wykonaniu powyższego polecenia. Hasło należy również przechować w trwałym i bezpiecznym miejscu. Kolejne pytania można pominąć wciskając przy każdym ENTER, jedynie w pytaniu o poprawność danych należy odpowiedzieć “yes”:
Po zakończeniu polecenia w bieżącym katalogu pojawi się plik keystore, w moim przypadku jest to myapp.keystore. Później wgramy go do Ionic Hub, teraz stwórzmy potrzebne pliki dla iOS.
iOS
Procedura dla iOS jest nieco dłuższa, przed przystąpieniem do jej wykonania należy utworzyć konto na stronie: https://developer.apple.com/ jeśli jeszcze takiego nie mamy.
Rejestrujemy identyfikator aplikacji
Na stronie https://developer.apple.com/account/resources/identifiers/list klikamy ikonę z plusem i pojawia nam się formularz:
Wybieramy “App IDs” i przechodzimy dalej. Znajdziemy się na ekranie z kolejnym formularzem:
Tutaj najważniejsze jest podanie w polu Bundle ID identyfikatora aplikacji zgodnego z tym co mamy w config.xml. Przychodzimy dalej, klikamy “Register” i po chwili na liście “Identifiers” widzimy nasz identyfikator.
Rejestracja urządzenia
W wersji deweloperskiej nasza aplikacja będzie działać tylko na urządzeniach, które do niej przypiszemy. Urządzenie dodajemy klikając ikonę plusa na stronie: https://developer.apple.com/account/resources/devices/list, otwiera się wówczas formularz:
Tutaj podajemy nazwę urządzenia widoczną tylko dla nas i jego “Device ID (UDID)”. Jeśli nie znasz UDID swojego urządzenia, użyj tego narzędzia: https://showmyudid.com/
Certificate Signing Request
Następnym krokiem jest wygenerowanie “Certificate Signing Request” – pliku który będzie potrzebny do wygenerowania certyfikatu.
Przejdźmy raz jeszcze do katalogu z naszymi kluczami i wykonajmy tam polecenia:
openssl genrsa -out <KEY_NAME>.key 2048
openssl req -new -key <KEY_NAME>.key -out CertificateSigningRequest.certSigningRequest
KEY_NAME w obu poleceniach zamieniamy na naszą nazwę, np. Myapp.key
Zostaniesz zapytany o dane kontaktowe, możesz je pominąć, podaj jednak hasło w pytaniu “A challenge password”.
W rezultacie otrzymamy plik CertificateSigningRequest.certSigningRequest, teraz możemy przystąpić do generowania certyfikatu.
Certyfikat
Na stronie https://developer.apple.com/account/resources/certificates/list kliknij ikonę plusa, otworzy się formularz:
Zaznaczamy “iOS App Development”, klikamy “Continue”, pokazuje się “Upload a Certificate Signing Request”, wgrywamy tu nasz poprzednio wygenerowany plik CertificateSigningRequest.certSigningRequest i przechodzimy dalej. Na kolejnym ekranie zobaczysz podsumowanie twojego certyfikatu i przycisk “Download” – kliknij go i zapisz plik z certyfikatem ios_development.cer.
Teraz musimy przekształcić plik, aby uzyskać plik .p12.
Wykonujemy dwa polecenia:
openssl x509 -inform DER -outform PEM -in ios_development.cer -out ios_development.cer.pem
openssl pkcs12 -export -inkey keyname.key -in ios_development.cer.pem -out Certificates.p12
W drugim z powyższych poleceń podajemy hasło, które będziemy musieli później podać w Ionic Hub.
Provisioning Profile
Ostatnią rzeczą, którą musimy zrobić na stronie Apple Developer jest wygenerowanie provisioning profile. Na stronie https://developer.apple.com/account/resources/profiles/list klikamy ikonę plusa i przechodzimy do formularza:
Zaznaczamy “iOS App Development” i klikamy “Continue”, następnie na stronie “Select an App ID” wybieramy z listy rozwijanej nasz identyfikator aplikacji i raz jeszcze klikamy “Continue”, na następnym ekranie zaznaczamy nasz certyfikat i przechodzimy dalej. Na ekranie “Select Devices” zaznaczamy poprzednio dodane urządzenia na których będziemy testować naszą aplikację i przechodzimy do ostatniego kroku, tutaj podajemy nazwę naszego profilu, np. MyProfile i klikamy przycisk “Generate”. Po wygenerowaniu, klikamy Download i zapisujemy plik .mobileprovision.
Ważna uwaga: jeśli w przyszłości będziemy chcieli dodać kolejne urządzenia do naszej aplikacji w wersji deweloperskiej, dodajemy je w zakładce devices a następnie edytujemy provisioning profile, zaznaczając nowe urządzenia, generujemy nowy plik, zapisujemy go ponownie i wgrywamy do Ionic Hub.
Wgranie certyfikatów w Ionic Hub
W tym momencie mamy już wszystkie potrzebne pliki (pamiętaj o utworzeniu kopii zapasowej dla nich i przechowywaniu haseł w bezpiecznym miejscu). Możemy wrócić do Ionic Hub.
W Ionic Hub wchodzimy do Package > Certificates, klikamy “Add Profile”, podajemy przyjazną nazwę, np. MyAppDev, w polu “type” wybieramy “Development” i klikamy create. Pokaże się nam formularz:
W zakładce iOS wypełniamy:
W zakładce Android wypełniamy:
Aby nie pogubić się w hasłach można we wszystkich miejscach podać takie samo hasło, choć ze względów bezpieczeństwa lepiej podawać różne i zapisywać je z odpowiednią adnotacją, pozwalającą określić które hasło jest do czego.
Budowanie paczek ipa i apk
Teraz możemy przystąpić do tworzenia paczki, przechodzimy do Package > Builds i klikamy “New Package Build”, następnie wybieramy commit z którego chcemy stworzyć paczkę, wybieramy OS, dla iOS wybieramy “iOS – XCode 10”, dla Androida wybieramy “Android”, w polu “Build Type” zaznaczamy Development dla iOS lub Debug dla Androida, w przypadku iOS wybieramy też nasz Security Profile (w przypadku androida i typu Debug nie musimy tego robić).
Klikamy “Package Build” i widzimy ekran z informacjami o budowaniu paczki:
Jeśli budowanie przejdzie bez błędów zobaczymy przycisk “Download IPA” lub “Download APK” zależnie od wybranego OS. Po kliknięciu przycisku zapisujemy plik na naszym komputerze.
Dystrybucja w trybie deweloperskim
Teraz, gdy mamy już stworzone paczki, możemy je zainstalować na naszym telefonie i wysłać do testerów. W tym celu polecam serwis https://www.diawi.com/ w którym znajdziemy taki formularz:
Przeciągamy naszą aplikację do pola “Drag&drop files here”, odznaczamy oba checkboxy u dołu, klikamy “More options” i podajemy hasło, które wyślemy testerom wraz z linkiem do aplikacji w diawi, opcjonalnie możemy podać nasz adres w polu “Email”, aby otrzymać link e-mailem.
Kiedy aplikacja wgra się do diawi i klikniemy “Send” pokażę nam się strona z QR Code, który możemy zeskanować na telefonie, aby zainstalować aplikację.
Uwaga: czasami aplikacja na Androidzie nie uruchamia się, a debugując ją znajdujemy logi dotyczące Play Protect, aby tego uniknąć warto zgłosić nasz identyfikator aplikacji na stronie: https://support.google.com/googleplay/android-developer/contact/protectappeals. Tą czynność wykonujemy jednorazowo.
Co dalej?
W tym momencie mamy skonfigurowane wszystko co potrzebne do budowania aplikacji w trybie deweloperskim. Procedura przy budowaniu aplikacji w trybie produkcyjnym wygląda podobnie, z tą różnicą, że w certyfikat w Apple Developer generujemy zaznaczając “iOS Distribution (App Store and Ad Hoc)” zamiast “iOS App Development”, a tworząc Security Profile w Ionic Hub zaznaczamy type “Production”.
Dystrybucja aplikacji w Google Play i App Store to temat na osobny artykuł, natomiast warto wspomnieć o jednej rzeczy: plik .ipa musimy wgrać do App Store Connect przy pomocy narzędzia AppLoader, które działa tylko na Macu, na szczęście z pomocą przychodzi serwis https://www.macincloud.com/ gdzie możemy wykupić dostęp do zdalnego Maca w opcji Pay-As-You-Go, czyli płacimy za godziny używania. Do wgrania aplikacji wystarczy nam zaledwie kilka minut, więc nie jest to drogie rozwiązanie.
Podsumowanie
Choć artykuł ten jest dość długi a cały proces wydaje się skomplikowany to po pierwszym przejściu przez wszystkie kroki będziecie wiedzieli z czym to się je i przy kolejnych aplikacjach większość rzeczy zrobicie już sami. Niemniej zachęcam do zachowania sobie linka do tego artykułu np. w zakładkach w przeglądarce, aby móc do niego wrócić gdy będzie potrzeba.
Laravel Dusk jest narzędziem do automatyzowania przeglądarki i testowania stron budowanych w Laravelu. Narzędzie to uruchamia i steruje ChromeDriver, dzięki czemu mamy możliwość automatycznego testowania naszych aplikacji w przeglądarce.
Test driven development to technika tworzenia oprogramowania, która opiera się na cyklu trzech następujących po sobie czynności: test czerwony -> test zielony -> refactoring. Więcej informacji na temat TDD można znaleźć w sieci, ja natomiast polecam książkę „TDD. Techniki programowania sterowanego testami” Dariusza Woźniaka, kod tej książki jest pisany w C#, ale zawarte w niej informacje są uniwersalne dla wszystkich języków programowania.
Dla potrzeb naszego artykułu musimy o TDD wiedzieć tyle, że najpierw piszemy test który zakończy się niepowodzeniem, później piszemy kod który powoduje że test kończy się powodzeniem, następnie robimy refactoring i przechodzimy do pisania kolejnego testu, tym samym zapętlając cykl.
Któż nie lubi posłuchać radia, jedni słuchają dla muzyki, inni dla informacji, a jeszcze inni po prostu włączają radio jako tło. W dzisiejszych czasach nie jesteśmy już ograniczeni tylko do stacji radiowych, które odbiera nasz odbiornik fm, możemy słuchać audycji z całego świata. W niniejszym artykule pokażę jak zbudować swój własny odbiornik radiowy działający na mini-komputerze Raspberry Pi, sterowany przez przeglądarkę z dowolnego urządzenia w sieci wi-fi. Sercem systemu będzie aplikacja w języku Python.
Na początek wystarczy Raspberry Pi z systemem Raspbian i podłączone do niego słuchawki, na końcu artykułu przedstawię możliwości rozbudowy naszego radia.
Kod źródłowy napiszemy w języku Python 3, do stworzenia prostego interfejsu webowego wykorzystamy framework Flask, zaś za odtwarzanie dźwięku odpowiadać będzie aplikacja Music Player Daemon (mpd) oraz prosty interfejs konsolowy o nazwie mpc. Lista stacji radiowych będzie pobierana z pliku YAML.
Aby zainstalować wszystkie potrzebne narzędzia w systemie Ubuntu lub Raspbian należy wykonać polecenia:
sudo apt-get update sudo apt-get install mpd mpc python-pip pip install -U Flask oyaml
Stwórzmy katalog w którym będzie się znajdował nasz projekt a w nim plik main.py
.
W pliku main.py
utwórzmy klasę i stwórzmy jej obiekt:
class Radio: def __init__(self): None radio = Radio()
Następnie dodajemy metodę odpowiedzialną za komunikację z daemonem mpd:
def mpcCommand(self, cmd): p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) return p.stdout.read()
Możemy już w tym momencie spróbować odtworzyć pierwszy stream dodając w metodzie __init__() kod:
self.mpcCommand(["mpc", "add", "http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws"]) self.mpcCommand(["mpc", "play"])
Zaimportujemy też moduł subprocess:
import subprocess
Po wykonaniu aplikacji stream zacznie się odtwarzać, a aplikacja się zakończy. Aby zakończyć odtwarzanie musimy w konsoli systemowej wykonać polecenie mpc stop
.
Jeśli wykonamy polecenie mpc playlist
, zobaczymy że do naszej playlisty została dodana stacja „http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws”. W celu uproszczenia komunikacji naszego skryptu z mpd, przed każdym rozpoczęciem odtwarzania będziemy czyścić listę i dodawać wybraną przez nas stację. Implementacja sprowadza się do dodania linii self.mpcCommand(["mpc", "clear"])
przed innymi wywołaniami self.mpcCommand()
. Dodatkowo na końcu naszej metody __init__(self) możemy dodać:
while True: None
Spowoduje to, że aplikacja będzie uruchomiona dopóki nie przerwiemy jej działania, na przykład kombinacją klawiszy CTRL+C. Przerwanie pracy aplikacji nie spowoduje jednak przerwania odtwarzania strumienia przez demon mpd, dlatego musimy dodać metodę exitHandler()
oraz zadeklarować jej wywołanie po zakończeniu aplikacji.
Dodajemy moduł atexit:
import atexit
oraz metodę:
def exitHandler(self): self.mpcCommand(["mpc", "stop"]) self.mpcCommand(["mpc", "clear"])
Jak widać metoda zatrzymuje odtwarzanie i czyści playlistę. Aby python wykonał tą metodę po zakończeniu aplikacji, należy metodzie __init__() dodać linijkę:
atexit.register(self.exitHandler)
Linia ta musi być umieszczona przed pętlą while True
.
Kolejnym krokiem będzie wczytanie listy stacji z pliku YAML. Przykładowy plik znajduje się tutaj, natomiast jego wczytanie wygląda następująco:
stationsFile = open("stations.yml", "r") data = yaml.load(stationsFile) self.stations = [] for k in data: self.stations.append({ "name": k, "url": data[k] })
Powyższy kod wczytuje zawartość pliku, ładuje go do zmiennej data
a następnie tworzy listę słowników self.stations
. Aby kod zadziałał musimy dodać jeszcze jeden moduł:
import oyaml as yaml
Użyłem oyaml zamiast PyYaml, ponieważ PyYaml nie zawsze wczytuje listę stacji w takiej kolejności jaką ustaliliśmy w pliku .yml, oyaml rozwiązuje ten problem.
Następnie usuwamy pętlę while True
a zamiast niej wstawiamy kod:
self.initWebUi()
Jest to wywołanie metody, której definicja wygląda następująco:
def initWebUi(self): app = Flask(__name__, template_folder="template") @app.route("/", methods=["GET", "POST"]) def control_page(title="Radio control"): if request.method == "POST": if request.form["submit"] == "Play": self.currentStationUrl = str(request.form["station"]) self.mpcCommand(["mpc", "clear"]) self.mpcCommand(["mpc", "add", self.currentStationUrl]) self.mpcCommand(["mpc", "play"]) elif request.form["submit"] == "Stop": self.mpcCommand(["mpc", "stop"]) return render_template("/control.html", title=title, stations=self.stations, currentStationUrl=self.currentStationUrl) app.run(host="0.0.0.0", port=1234)
Dodajemy też moduły:
from flask import Flask from flask import render_template from flask import request
Metoda initWebUi() inicjuje framework flask i definuje prosty routing wewnątrz którego jest akcja control_page
wyświetlająca szablon z pliku template/control.html
oraz obsługująca komendy „Play” i „Stop”. Plik szablonu znajduje się tutaj.
Dodatkowo w metodzie __init__() musimy dodać:
self.currentStationUrl = None
W tym momencie możemy otworzyć w przeglądarce adres http://0.0.0.0:1234/ i zobaczymy prosty panel pozwalający na wybór stacji i rozpoczęcie lub zatrzymanie odtwarzania.
Pełny kod aplikacji umiesciłem się w repozytorium na GitHub https://github.com/jakubthedeveloper/PythonInternetRadio, znajduje się w nim kod z artykułu z kilkoma usprawnieniami, na przykład możliwość podania w argumentach wywołania skryptu adresu i portu na którym ma działać nasze webowe UI. W pliku README.md znajdziemy również informację jak uruchomić projekt na mini-komputerze Raspberry Pi.
Dodatkowo kod w repozytorium został zrefaktoryzowany, poszczególne funkcje zostały przeniesione do odpowiednich klas, dodałem też unit testy.
W momencie gdy na słuchawkach podpiętych do Raspberry Pi słyszymy stację radiową wybraną w naszym webowym interfejsie mamy doskonały punkt wyjścia, żeby zbudować coś ciekawszego. Kilka pomysłów:
Zachęcam do eksperymentowania i podsyłania waszych realizacji.
Już po napisaniu powyższego artykułu dokonałem wielu modyfikacji, które znajdziecie w repozytorium projektu. Jedną z nich jest modyfikacja interfejsu webowego z wykorzystaniem Bootstrap i jQuery:
Moje radyjko zbudowane z wykorzystaniem rozwiązania przedstawionego w niniejszym artykule opiera się na następującej architekturze:
Mieszanie kreatywności z nudą i odrobiną wolnego czasu bywa zaskakujące w skutkach, u mnie dziś taka mieszana zaowocowała urządzeniem, które pokazuje powiadomienie o nieprzeczytanej poczcie w postaci ikony koperty narysowanej flamastrem na kawałku tektury, powiadomienie wyskakuje zza monitora po nadejściu nowej wiadomości i chowa się gdy wszystkie wiadomości są przeczytane.
Tutaj możecie zobaczyć urządzenie w akcji:
Do zbudowania „powiadamiacza” użyłem:
Kod jest napisany w:
Kompletny zestaw prezentuje się następująco:
Kod projektu umieściłem na GitHubie: https://github.com/jakubthedeveloper/RealMailNotification
Aplikację napisaną w pythonie uruchamiamy poleceniem:
python3 checker.py [-h] [--serial-port SERIAL_PORT] [--imap-server IMAP_SERVER] --imap-user IMAP_USER
Jeśli nie podamy adresu serwera IMAP, zostanie użyty adres imap.gmail.com, domyślną wartością parametru –serial-port jest /dev/ttyUSB0, natomiast parametr –imap-user jest obowiązkowy. Przykład:
python3 checker.py --imap-user moje.konto@gmail.com
Więcej informacji o uruchomieniu skryptu znajduje się w pliku readme.
Po uruchomieniu, skrypt sprawdza pocztę na serwerze i wysyła na port szeregowy (usb) tekst ‚mail’ lub ‚nomail’, zależnie czy są nieprzeczytane wiadomości czy też nie.
Aplikacja dla Arduino nasłuchuje na porcie szeregowym i ustawia serwo w jednej z dwóch predefiniowanych pozycji, zależnie od otrzymanej komendy. Poziome ustawienie zamocowanej do serwo tekturki pozwala jej się schować za monitorem, natomiast w ustawieniu pionowym tektura wystaje nad górną krawędź monitora.
Filmik z testów:
Największym problemem było znalezienie sposobu na zamontowanie urządzenia z tyłu monitora, na szczęście z pomocą przyszły nawiercone kątowniki, śrubki i trytytki 🙂
Na pytanie „Czym zajmuje się programista?” przyszło mi odpowiedzieć w życiu co najmniej kilkanaście razy w rozmowach z rodziną i znajomymi, za każdym razem odpowiedź na to pytanie była nieco inna, w zależności od poziomu znajomości świata IT mojego rozmówcy.
Najogólniej mówiąc, programowanie polega na pisaniu programów komputerowych w specjalnym języku zrozumiałym dla komputerów.
Niezależnie czy pojęcia takie jak “Web-development” lub “backend” są ci znane, czy może brzmią dla ciebie jak nazwy magicznych wywarów, ten artykuł jest dla ciebie. Jeśli słyszałeś kiedyś rozmowę dwóch programistów lub czytałeś co programiści piszą w internecie (również na tym blogu) i stwierdziłeś że nie masz pojęcia o co w tym wszystkim chodzi, a chciałbyś to zrozumieć przynajmniej w stopniu podstawowym, zachęcam do lektury niniejszego tekstu.
Przedstawię kilka dialogów z różnymi osobami, podczas których starałem się wyjaśnić, czym zajmuję się zawodowo. Na końcu artykułu przedstawię czym się zajmuję moimi słowami, bez odniesienia do konkretnego poziomu wiedzy czytelnika.
Jednym z zagadnień należących do zakresu pracy programisty jest rozwiązywanie różnego rodzaju problemów, wśród nich znajduje się optymalizacja algorytmów.
Problemy tego typu polegają na tym, że mamy do zaimplementowania pewną funkcjonalność, która musi działać w określonych warunkach, określonym czasie i spełniać zadane założenia. Zatem nie wystarczy że coś działa, musi to też działać odpowiednio szybko i bez nadmiernego zużywania zasobów.
Załóżmy że mamy wskazówkę, która obraca się wokół tarczy zawsze o 90 stopni w prawo.
Początkowe położenie to 0 stopni.
Naszym zadaniem jest napisanie funkcji, która określa w jakim położeniu znajdzie się wskazówka po określonej liczbie obrotów.
W pewnym momencie mojej kariery na stanowisku programisty stanąłem przed dylematem „co dalej?”. Z piętnastoletnim doświadczeniem zawodowym, masą ukończonych projektów, zadowolonych klientów, sporą siecią kontaktów i całkiem niezłą renomą wśród współpracowników poczułem że dotarłem do „sufitu” czyli tam gdzie wyżej się już nie da pójść.
Z jednej strony chciałem nadal zajmować się programowaniem, architekturą systemów, rozwiązywaniem problemów, z drugiej jednak odczułem już lekkie zmęczenie patrzeniem się w IDE oraz konsolę przez cały dzień mojej pracy, postanowiłem więc rozejrzeć się za czymś co pozwoli mi być nadal blisko programowania, ale może trochę więcej pracować w inny sposób, z ludźmi. Po kilku rozmowach z moją Business Manager oraz po jej rozmowach z innymi osobami na szczeblu menadżerskim doszliśmy do wniosku, że to czego szukam to rola Team Leadera.
Załóżmy że mamy napisaną lub dopiero piszemy aplikację w PHP, która używa zewnętrznego API i z zwraca dane poprzez swoje własne API, czyli jest pośrednikiem.
Chcemy napisać testy naszych endpointów tak, żeby nie wykonywać zapytań do zewnętrznego API w czasie testów.
Jeden z naszych endpointów zwraca informacje o produkcie, jego adres to GET /product/{id}.
Nasz test mógłby wyglądać tak:
public function test_it_should_return_product() { $response = $this->get('/products/' . $this->faker->randomNumber()); $response->assertStatus(200); $response->assertJsonStructure([ "id", "name", "price" ]); }
W naszym kontrolerze używamy interfejsu ProductInterface który jest implementowany przez klasę ProductRepository, a ta z kolei używa klasy ProductProxy do wykonania zapytania do API. Klasas ProductProxy dziedziczy ogólną klasę BaseProxy, która zawiera metodę sendRequest(), to właśnie ta metoda odpowiada za wszelkie requesty HTTP do zewnętrznego API. Na początek więc zróbmy mock tej metody, aby upewnić się, że żaden z naszych testów nie wykona prawdziwego zapytania do zewnętrznego API.