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ć.

W dziale „Na każdy temat” umieszczam różne wpisy nie będące pełnymi artykułami. Są to różne ciekawostki, skrypty oraz sposoby rozwiązywania różnych problemów informatycznych.
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.
Postanowiłem w tym roku wziąć udział w Game Off 2020 w serwisie itch.io. Jest to game jam, w którym należy wykonać grę na zadany temat. W tym roku tematem jest: Moonshot.
Znaczenia słowa moonshot:
moonshot thinking
rodzaj myślenia, który ma na celu osiągnięcie czegoś, co powszechnie uważa się za niemożliwe
Gra którą wymyśliłem (z nieocenioną pomocą moich dzieci) polega na wystrzeliwaniu astronauty na księżyc… przy pomocy katapulty 🙂 Zatem mamy tutaj i wystrzelenie na księżyc i coś co powszechnie uważa się za niemożliwe. Grę napisałem w języku Python, wykorzystując bibliotekę PyGame.
W repozytorium github umieściłem kod projektu napisanego w pythonie z użyciem pygame, który jest prostą zabawką nad którą spędziłem kilka godzin programując z dziećmi i pokazując jakie wyzwania napotykamy pracując nad grami komputerowymi. Narzędzie to generuje prosty krajobraz w stylu gier retro:
Behat jest frameworkiem Behavior-driven development (w skrócie BDD) dla języka PHP, który pomaga w implementacji i testowaniu założeń biznesowych. Oficjalna dokumentacja Behata znajduje się na stronie https://docs.behat.org/.
Instalacja behata sprowadza się do zainstalowania paczki przy użyciu composera:
composer require --dev behat/behat
Następnie należy zainicjować behata, poleceniem:
$ vendor/bin/behat --init
Polecenie to stworzy katalog features i wypisze informacje na temat jego zawartości:
+d features - place your *.feature files here +d features/bootstrap - place your context classes here +f features/bootstrap/FeatureContext.php - place your definitions, transformations and hooks here
Podstawymi elementami Behata są pliki .feature oraz klasy kontekstu, powyższy rezultat pokazuje gdzie należy umieścić każde z nich.
Plik .feature jest to plik w formacie zwanym Gherkin lub Cucumber, opisujący dane rozwiązanie. Format opisu scenariuszy powinien być zrozumiały dla osób nietechnicznych. Na początku zawsze znajduje się opis danego rozwiązania, np.:
Feature: In order to buy products as a customer I have to put products into my basket and have enough money to pay for them.
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.
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.