Internet Of Things: Connecting Things - Rozdział 3

1. Czujniki i elektronika pozwalają nam połączyć świat fizyczny z systemem obliczeniowym, takim jak mikrokontroler. To połączenie pozwala nam wykonać pierwszy krok do stworzenia rozwiązania IoT. Najpierw odczytujemy dane ze świata fizycznego, a potem coś z nimi robimy. Albo je przechowujemy, przesyłamy, albo przetwarzamy. W świecie cyfrowym przetwarzanie danych odbywa się za pomocą programów komputerowych. Program to zestaw uporządkowanych instrukcji stworzonych do wykonania określonego zadania. Na podstawie tej definicji wiele codziennych czynności można uznać za programy.
Programy komputerowe podobnie jak przepis na chleb, czy ciasto, są również zestawem uporządkowanych instrukcji stworzonych do wykonania określonego zadania. Nazywane również kodem, programy komputerowe mogą być pisane w kilku różnych językach. Składnia i zasady różnią się w zależności od języka, ale logika programu powinna się zmieniać niewiele lub wcale.

2. Komputer to każde urządzenie zawierające CPU, pamięć i urządzenia wejścia/wyjścia (monitor, klawiatura, mysz, karta dźwiękowa itp.). Komputery stacjonarne, smartfony, tablety, zegarki cyfrowe i inteligentne urządzenia to tylko niektóre przykłady komputerów. Pomimo że komputery są wszędzie, są bezużyteczne, dopóki nie uruchamiają programów.

Programy komputerowe przybierają wiele różnych form. Systemy operacyjne, oprogramowanie układowe i aplikacje to przykłady programów znajdujących się w komputerach.

System operacyjny (OS) to program, który umożliwia użytkownikom interakcję z komputerami. Nowoczesne systemy operacyjne zawierają graficzne interfejsy ułatwiające interakcję użytkownika. Przykładami systemów operacyjnych są Windows, Linux, OS X, Apple iOS i Android.

Oprogramowanie układowe to programy stworzone, aby umożliwić komputerowi wykonywanie określonego zadania. Znajduje się ono w małych komputerach - np. zegarkach cyfrowych (nie smartwatchach - tam jest już często Android!), czy urządzeniach AGD. Ze względu na ograniczoną pamięć i inne ograniczenia zasobów, urządzenia IoT często polegają na oprogramowaniu układowym do swojego działania. Funkcjonalność oprogramowania układowego i systemu operacyjnego często się pokrywa. W niektórych przypadkach oprogramowanie układowe może również pełnić rolę systemu operacyjnego dla prostszych komputerów.

3. Wyrażenia to kombinacje zmiennych, stałych i operatorów, które dają nową wartość. Funkcje definiują sekwencję wyrażeń, które należy zastosować do argumentów (x,y), aby uzyskać wartość zwracaną z. Za pomocą określonych struktur logicznych programista może przygotować komputer do podejmowania decyzji.
  • IF – ELSE: Ta struktura logiczna pozwala komputerowi podjąć decyzję na podstawie wyniku wyrażenia.  Przykładem wyrażenia jest myVar > 0. To wyrażenie jest prawdziwe, jeśli wartość przechowywana w zmiennej myVar jest większa od zera. Gdy interpreter lub kompilator napotka strukturę IF-ELSE, ocenia podane wyrażenie. Jeśli wyrażenie jest fałszywe, komputer przechodzi do następnej struktury, ignorując zawartość bloku IF-ELSE. Jeśli wyrażenie jest prawdziwe, komputer wykonuje powiązaną akcję, zanim przejdzie do następnej instrukcji w programie.
  • Pętla FOR – Służą do wykonania określonego zestawu instrukcji określoną liczbę razy, na podstawie wyrażenia. Termin pętla pochodzi od faktu, że zestaw instrukcji jest wykonywany wielokrotnie. Choć składnia pętli FOR różni się w zależności od języka, koncepcja pozostaje taka sama: definiuje się zmienną, która pełni rolę licznika i maksymalną wartość dla niej. Za każdym razem, gdy pętla jest wykonywana, zmienna licznika jest zwiększana. Gdy licznik jest równy zdefiniowanej maksymalnej wartości, pętla jest porzucana i wykonanie przechodzi do następnej instrukcji.
  • WHILE Loops – Służą do wykonania określonego zestawu instrukcji, dopóki wyrażenie jest prawdziwe. Zauważ, że często instrukcje wewnątrz pętli ostatecznie sprawiają, że wyrażenie ocenia się jako fałszywe.
np. w języku C++:

#include <iostream>
using namespace std;

int main() {
  // deklarujemy zmienną n i przypisujemy jej wartość 10
  int n = 10;
  
  // używamy pętli for, aby wyświetlić liczby od 1 do n
  cout << "Liczby od 1 do " << n << " to:\n";
  for (int i = 1; i <= n; i++) {
    cout << i << " ";
  }
  cout << "\n"; // przejście do nowej linii
  
  // używamy pętli while, aby znaleźć największy dzielnik n mniejszy od n
  int d = n - 1; // zaczynamy od d = n - 1
  while (d > 0) { // dopóki d jest dodatnie
    if (n % d == 0) { // jeśli n jest podzielne przez d
      break; // przerwij pętlę
    }
    d--; // zmniejsz d o 1
  }
  
  // używamy instrukcji if-else, aby sprawdzić, czy znaleźliśmy dzielnik
  if (d > 0) { // jeśli d jest dodatnie
    cout << "Największy dzielnik " << n << " mniejszy od " << n << " to " << d << "\n";
  }
  else { // w przeciwnym razie
    cout << n << " nie ma dzielników mniejszych od " << n << "\n";
  }
  
  return 0;
}

// -> to komentarze w języku C++ (wszystko co po "//" nie zostanie wykonane przez kompilator

4. Języki komputerowe można podzielić na:
  • kompilowane (polegają na innym programie, który analizuje i wykonuje kod. Ten program nazywa się interpreterem. Kod pozostaje w czytelnym dla człowieka tekście i jest podawany do interpretera do wykonania. Choć języki interpretowane ułatwiają utrzymanie i rozwiązywanie problemów z kodem, wykonanie jest również wolniejsze niż w językach kompilowanych. Przykładami języków interpretowanych są Python, JavaScript i PHP)
  • interpretowane (polegają na kompilatorze, innym programie, który zamienia czytelny dla człowieka kod na binarny kod wykonywalny. Skompilowany kod jest przechowywany w postaci binarnej i może być wykonywany w dowolnym momencie bez potrzeby ponownej kompilacji. Skompilowany kod działa również szybciej, ponieważ jest wykonywany bezpośrednio przez procesor, bez potrzeby użycia interpretera. Kod źródłowy to termin używany do określenia kodu języka kompilowanego przed jego kompilacją. Jeśli programista chce wprowadzić zmiany do skompilowanego programu, musi zastosować je do kodu źródłowego i ponownie go skompilować przed wykonaniem. Przykładami języków kompilowanych są C++, C#
5. Podobnie jak w przypadku języków ludzkich, istnieje kilka różnych języków komputerowych. Niektóre języki komputerowe są lepsze od innych w pewnych rodzajach zadań.
  • JavaScript, interpretowany język komputerowy, jest przeznaczony do tworzenia aplikacji internetowych.
  • Python, kolejny język interpretowany (ale jest również kompilowany), pozwala na prostsze instrukcje. Python jest bardzo łatwy w użyciu, potężny i wszechstronny i stał się językiem wyboru dla wielu programistów IoT. Posiada dużo modułów, które można zaimportować.
  • Rodzina języków C (C, C++, C#), skompilowany język, jest świetny do tworzenia złożonych i szybkich programów, ale jego ścisłe zasady i składnia sprawiają, że jest trudniejszy w opracowaniu.
  • Blockly to wizualny język programowania, który pozwala użytkownikom tworzyć programy poprzez łączenie bloków, reprezentujących różne struktury logiczne języka, zamiast pisać faktyczny kod.
  • Java to skompilowany język “napisz raz, uruchom wszędzie” (WORA).Java jest zaprojektowana tak, aby działać na dowolnej platformie bez potrzeby rekompilacji. (Java i JavaScript nie są spokrewnione!)
6. Powszechnym zastosowaniem systemów IoT jest zbieranie danych. Zbieranie danych jest ważne, ale dane muszą być przetworzone, zanim będą użyteczne. Zebrane dane mogą być przetwarzane blisko miejsca zbierania lub mogą być transmitowane i przechowywane w chmurze do późniejszego przetworzenia. Często dane z kilku źródeł są łączone, aby zapewnić najbardziej przydatne informacje. Programy komputerowe są używane do efektywnego przetwarzania zebranych danych.

7. Ważnym aspektem systemu IoT jest jego zdolność do podejmowania decyzji np. uruchomienie alarmu jeżeli poziom dwutlenku węgla przekroczy próg. Niektóre urządzenia IoT są zdolne do bardziej zaawansowanych rzeczy - np. rozpoznawanie twarzy. 

8. Interfejs programowania aplikacji (API) to zestaw procedur i narzędzi oprogramowania, które ułatwiają komunikację między programami. Dzięki API aplikacje działające w sieciach mogą komunikować się ze sobą, wymieniać dane i prosić o konkretne usługi od innych aplikacji, takie jak zapytanie zewnętrznego API, czy osoba na zdjęciu jest mężczyzną czy kobietą. Dostępne są różne rodzaje API, w tym API systemu operacyjnego, API aplikacji i API stron internetowych. Tworząc aplikację menedżera plików, programista oprogramowania będzie korzystał z API systemu operacyjnego, aby skopiować, przenieść lub usunąć plik. Aplikacje IoT mogą rozmawiać ze sobą za pomocą API, ale mogą również używać API do komunikowania się z różnymi usługami opartymi na chmurze.


Przykład: TUTAJ!

9. Representational State Transfer (REST), czyli usługi sieciowe RESTful, to rodzaj API zaprojektowanego tak, aby ułatwić interakcję programów przez Internet. API REST wykorzystuje wywołania oparte na protokole HTTP między różnymi aplikacjami do dostępu i manipulowania informacjami przechowywanymi w potężnych bazach danych. 

Zasoby sieciowe były kiedyś identyfikowane wyłącznie przez URL. Dziś zasoby sieciowe obejmują każdą jednostkę lub rzecz, która może być nazwana, zidentyfikowana lub zaadresowana. API REST wykorzystuje protokół HTTP i URL lub URI do żądania usług sieciowych. Takie żądania sieciowe oparte na REST uruchamiają odpowiedzi w dobrze zdefiniowanych formatach sieciowych, takich jak XML i JSON (JavaScript Object Notation). Korzystając z protokołu HTTP jako usługi RESTful, mogą pożyczyć operacje HTTP, w tym HTTP GET, POST, PUT i DELETE.

10. System IoT składa się z połączenia kilku bloków funkcjonalnych: urządzeń, bramek, sieci, chmury i właściwej aplikacji. Na każdym z tych bloków działa kod, który spełnia funkcję, do której został zaprojektowany. Zalecane najlepsze praktyki dotyczące zapewnienia bezpieczeństwa połączonych urządzeń w IoT muszą obejmować:
  • Urządzenia powinny chronić się przed atakami, które utrudniają jego funkcjonowanie lub pozwalają na wykorzystanie go do niezamierzonych celów bez upoważnienia.
  • Urządzenia powinny chronić prywatne dane uwierzytelniające i klucze przed ujawnieniem nieuprawnionym stronom.
  • Urządzenia powinny chronić informacje odbierane, przesyłane lub przechowywane lokalnie na urządzeniu przed nieodpowiednim ujawnieniem nieuprawnionym stronom.
  • Urządzenia powinny chronić się przed byciem wykorzystanym jako wektor do atakowania innych urządzeń lub hostów w Internecie.
Zabezpieczenie urządzeń IoT w nietradycyjnych lokalizacjach jest trudniejsze. Urządzenia powinny być wyprodukowane tak, aby były odporne na ingerencje, a także umieszczone tak, aby nie były oczywiste i bardzo trudno dostępne.

Jednym ze sposobów, w jaki haker może zmienić funkcję urządzenia, jest uzyskanie dostępu do niego, wyłączenie jego funkcji, zainstalowanie nowego oprogramowania na urządzeniu i ponowne uruchomienie go. Innym sposobem ochrony urządzenia jest zapewnienie, że kod na urządzeniu (zarówno oprogramowanie układowe, jak i aplikacja) jest oryginalnym kodem, który został utworzony.

Dane powinny być szyfrowane podczas odbierania lub przesyłania do lokalnych i zdalnych serwerów. Zdalny dostęp do serwerów lub zdalnych punktów końcowych powinien być również zabezpieczony. Zapewnia to integralność danych, ponieważ są one chronione przed nieuprawnionym dostępem i ingerencją. Algorytmy szyfrowania i bezpieczne protokoły transmisji to techniki powszechnie stosowane do zabezpieczania oprogramowania i danych.

11. Raspberry Pi to tani, mały komputer. Posiada kilka portów USB, które można wykorzystać do podłączania różnych urządzeń, w tym klawiatur, myszy, dysków zewnętrznych i kamer. RaPi zawiera również 40-pinowy nagłówek z GPIO. Piny GPIO (General Purpose Input/Output pins), są niezwykle przydatne przy interakcji ze światem fizycznym. Czujniki, siłowniki, przełączniki i urządzenia można podłączyć do GPIO i sterować nimi za pomocą kodu uruchomionego na RaPi.


12. Raspberry Pi można używać na dwa sposoby: jako zwykły PC z monitorem, klawiaturą i myszą lub jako urządzenie IoT sterowane zdalnie przez sieć. W obu przypadkach trzeba zainstalować system operacyjny na karcie micro SD i podłączyć RaPi do zasilania. Aby używać RaPi jako PC, trzeba podłączyć również ekran HDMI i klawiaturę USB. Aby używać RaPi jako urządzenia IoT, trzeba skorzystać z rozwiązania o nazwie Prototyping Lab Application (PL-App), które umożliwia dostęp do RaPi bezpośrednio z sieci. PL-App składa się z kilku składników i obsługuje zarówno interfejs graficzny, jak i tekstowy.

13. Linux jest systemem operacyjnym otwarto źródłowym, szybkim, niezawodnym. Wymaga bardzo małych zasobów sprzętowych do działania i jest wysoce konfigurowalny. Linux jest częścią kilku platform i można go znaleźć w wielu miejscach. Innym ważnym aspektem Linuksa jest to, że jest on zaprojektowany do pracy w sieci. Operacje sieciowe i połączenia są proste w Linuksie, co czyni go dobrym wyborem dla profesjonalistów i administratorów sieci. Każda osoba może uzyskać kod źródłowy jądra, przejrzeć go, zmodyfikować i ponownie skompilować wedle własnego uznania. Firmy i użytkownicy mogą modyfikować, ponownie pakować i uruchamiać oprogramowanie. Mogą również rozpowszechniać program z opłatami lub bez nich. Dystrybucja Linuksa to termin używany do opisania różnych pakietów Linuksa tworzonych przez różne firmy. Dystrybucje Linuksa zawierają jądro Linuksa oraz szereg spersonalizowanych narzędzi i pakietów oprogramowania. Przykładowymi dystrybucjami są Debian, Mint, czy Ubuntu.

14. System operacyjny Linux można podzielić na jądro i powłokę. Jądro można postrzegać jako sam system operacyjny, natomiast powłoka to tylko program działający na systemie operacyjnym i oferujący funkcjonalność interakcji użytkownika z systemem operacyjnym.

Aby interakcja z sprzętem komputera była możliwa, użytkownik wchodzi w interakcję z powłoką, która wchodzi w interakcję z jądrem, które z kolei wchodzi w interakcję ze sprzętem. Powłoka jest interpreterem poleceń.  Gdy użytkownik loguje się do systemu, program logowania sprawdza nazwę użytkownika i hasło; jeśli dane uwierzytelniające są poprawne, program logowania wywołuje powłokę. Od tego momentu upoważniony użytkownik może zacząć wchodzić w interakcję z systemem operacyjnym za pomocą poleceń tekstowych. Chociaż wiele nowoczesnych dystrybucji Linuxa zawiera wsparcie dla graficznych interfejsów użytkownika (GUI), powłoka jest nadal uważana za najbardziej efektywną metodę interakcji z systemem.

Przykład interakcji użytkownik-powłoka-jądro: użytkownik chce usunąć plik o nazwie myFile i wpisuje rm myFile. Powłoka szuka programu rm i prosi jądro o wykonanie programu rm z parametrem myFile. Gdy proces jest uruchomiony, powłoka jest niedostępna dla użytkownika. Gdy proces zostanie zakończony, powłoka wyświetla użytkownikowi monit z wynikiem działania polecenia.

15. Wiele różnych powłok zostało stworzonych i wiele funkcji zostało dodanych, aby ułatwić wpisywanie i interakcję z użytkownikiem. Wśród najpopularniejszych powłok są Bourne Shell (sh), Bash (bash), C Shell (csh), ulepszona C Shell (tcsh) i Z Shell (zsh). Wybór powłoki to kwestia preferencji dla większości użytkowników.

Chociaż CLI nadal jest obecne, nowoczesny system operacyjny często uruchamia się w trybie GUI domyślnie. Jednym ze sposobów dostępu do CLI w systemie operacyjnym opartym na GUI jest poprzez aplikację emulatora terminala. Na Linuxie popularne emulatory terminala to Terminator, eterm, xterm, konsola i gnome-terminal.

Bez względu na używany emulator terminala, użytkownik nadal decyduje, jakiej powłoki używać w aplikacji emulatora terminala. Aby zmienić powłokę, użytkownik musi mieć żądaną powłokę zainstalowaną w systemie i skonfigurować kilka opcji w pliku konfiguracyjnym.

16. Podstawowe komendy dla terminala Linuxa:
  • grep - wyszukuje wzorce w plikach lub strumieniach danych.
  • ifconfig - konfiguruje i wyświetla informacje o interfejsach sieciowych.
  • apt-get - narzędzie do zarządzania pakietami w systemach opartych na Debianie.
  • pwd - wyświetla bieżącą ścieżkę katalogu roboczego.
  • cat - wyświetla zawartość plików lub łączy je i przekazuje do standardowego wyjścia.
  • man - wyświetla strony podręcznika dla podanej komendy.
  • ls - wyświetla zawartość katalogu.
  • cd - zmienia bieżący katalog roboczy.
  • mkdir - tworzy nowy katalog.
  • rm - usuwa pliki lub katalogi.
  • cp - kopiuje pliki lub katalogi.
  • mv - przenosi lub zmienia nazwę plików lub katalogów.
  • ps - wyświetla informacje o aktualnie działających procesach.
  • kill - wysyła sygnał do procesu, zwykle w celu zakończenia jego działania.
  • top - wyświetla dynamicznie aktualizowaną listę procesów zużywających najwięcej zasobów systemowych.
  • ping - wysyła pakiety ICMP ECHO_REQUEST do hosta sieciowego i mierzy czas odpowiedzi.
  • ssh - nawiązuje bezpieczne połączenie z innym komputerem za pomocą protokołu SSH.
  • tar - archiwizuje i kompresuje pliki i katalogi.
  • find - wyszukuje pliki i katalogi na podstawie określonych kryteriów.
  • nano - prosty edytor tekstu działający w trybie tekstowym.
17. W systemie Linux większość jednostek jest traktowana jako pliki. W celu zorganizowania systemu i wzmocnienia granic wewnątrz systemu, Linux używa uprawnień do plików. Każdy plik w systemie Linux posiada swoje uprawnienia do plików, określające co użytkownik, grupa i inni mogą zrobić z plikiem. Możliwe prawa dostępu to Odczyt, Zapis i Wykonanie.

Uprawnienia do plików są podstawową częścią systemu Linux i nie można ich złamać. Użytkownik ma tyle praw do pliku, ile pozwala na to uprawnienia tego pliku. Jedynym użytkownikiem, który może nadpisać uprawnienia do plików w systemie Linux, jest użytkownik root. Mając moc nadpisania uprawnień do plików, użytkownik root może zapisywać do dowolnego pliku.

Uprawnienia do plików to prosty koncept, ale niezwykle ważny dla systemu Linux, ponieważ to właśnie dzięki uprawnieniom do plików system strukturyzuje swoje bezpieczeństwo i definiuje granice. Zwykły użytkownik nie będzie mógł modyfikować plików lub zasobów, które do niego nie należą. W wyniku tej właściwości, dostęp do roota jest często wymagany przed przeprowadzeniem konserwacji i zadań administracyjnych.

18. Menedżer pakietów to zestaw narzędzi programistycznych zaprojektowanych do ułatwienia instalacji, usuwania i aktualizacji programów komputerowych. Różne systemy operacyjne zawierają różne menedżery pakietów. Menedżer pakietów zwykle zawiera narzędzia użytkownika i zdalne repozytorium pakietów. Narzędzia użytkownika ułatwiają zarządzanie pakietami i mogą być CLI lub GUI.

Przed wykonaniem jakiejkolwiek operacji na pakiecie należy zsynchronizować lokalny indeks repozytorium z indeksem zdalnym. W oparciu o decyzję użytkownika o uaktualnieniu pakietu lub nie, menedżer pakietów pobiera niezbędne pakiety. Po zakończeniu pobierania menedżer pakietów automatycznie instaluje je wszystkie.

Ponieważ Raspbian jest pochodną Debiana, dpkg i apt są domyślnie dołączone. Instalowanie, usuwanie i aktualizowanie pakietów w Raspberry Pi można łatwo wykonać za pomocą kilku prostych poleceń.

19. Blockly jest narzędziem do wizualnego programowania. Korzystając z różnych typów bloków, Blockly umożliwia użytkownikowi stworzenie programu bez wpisywania żadnych linii kodu.  Bloki zawierają również sloty i przestrzenie, które pozwalają programistom wprowadzać wartości wymagane przez strukturę. Programiści mogą łączyć ze sobą struktury programistyczne poprzez przeciąganie i dołączanie odpowiednich bloków. Struktury programistyczne takie jak warunki, pętle i zmienne są dostępne do użycia.

20. Python to język interpretowany, co oznacza, że do analizy i wykonania kodu Pythona potrzebny jest interpreter. Interpreter Pythona rozumie i wykonuje kod Pythona. Dzięki temu, że kod Pythona można tworzyć w dowolnym edytorze tekstowym, a także dostępne są interpretery Pythona dla wielu systemów operacyjnych, programiści. Istnieją również narzędzia firm trzecich, takie jak Py2exe i Pyinstaller, które umożliwiają spakowanie kodu źródłowego Pythona w plik wykonywalny, eliminując potrzebę posiadania interpretera Pythona przy uruchamianiu kodu. 

Python to język interpretowany, co oznacza, że do analizy i wykonania kodu Pythona potrzebny jest interpreter. Interpreter Pythona rozumie i wykonuje kod Pythona. Dzięki temu, że kod Pythona można tworzyć w dowolnym edytorze tekstowym, a także dostępne są interpretery Pythona dla wielu systemów operacyjnych, programiści Pythona mogą tworzyć i uruchamiać programy Pythona praktycznie na każdym systemie. Istnieją również narzędzia firm trzecich, takie jak Py2exe i Pyinstaller, które umożliwiają spakowanie kodu źródłowego Pythona w plik wykonywalny, eliminując potrzebę posiadania interpretera Pythona przy uruchamianiu kodu.

Na maszynach z systemem Linux, interpreter Pythona zwykle jest zainstalowany w katalogu /usr/bin/python lub /usr/bin/python3.

Oto krótkie wyjaśnienie podstaw języka Python:

Zmienne są nazwami, które odnoszą się do wartości przechowywanych w pamięci komputera. Aby użyć zmiennej, należy najpierw ją zadeklarować, nadając jej nazwę i przypisując jej wartość za pomocą operatora `=`. Na przykład: `x = 10` oznacza, że zmienna `x` ma wartość 10. Można następnie używać zmiennej `x` w wyrażeniach lub instrukcjach. Na przykład: `print(x + 5)` wyświetli 15 na ekranie. Zmienne mogą przechowywać różne typy danych, takie jak liczby całkowite (`int`), liczby zmiennoprzecinkowe (`float`), ciągi znaków (`str`), listy (`list`) i inne.

Importowanie modułów oznacza załadowanie kodu napisanego przez kogoś innego do własnego programu. Moduły zawierają funkcje, klasy i zmienne, które można wykorzystać w swoim kodzie. Aby zaimportować moduł, należy użyć słowa kluczowego `import` i podać nazwę modułu. Na przykład: `import math` załaduje moduł `math`, który zawiera funkcje matematyczne, takie jak `math.sqrt` (pierwiastek kwadratowy) czy `math.pi` (liczba pi). Można następnie używać tych funkcji w swoim kodzie poprzedzając je nazwą modułu i kropką. Na przykład: `print(math.sqrt(25))` wyświetli 5 na ekranie.

- Instrukcja `if-then` służy do wykonania pewnego bloku kodu tylko wtedy, gdy spełniony jest jakiś warunek. Składnia instrukcji `if-then` jest następująca:

if warunek:
    blok kodu

Warunek jest wyrażeniem logicznym, które może być prawdziwe (`True`) lub fałszywe (`False`). Blok kodu jest wcięty względem słowa kluczowego `if` i zawiera instrukcje, które mają być wykonane, jeśli warunek jest prawdziwy. Na przykład:

x = 10
if x > 0:
    print("x jest dodatnie")

Ten kod wyświetli "x jest dodatnie" na ekranie, ponieważ warunek `x > 0` jest prawdziwy.

Można również dodać opcjonalną klauzulę `else`, która określa blok kodu do wykonania, jeśli warunek jest fałszywy. Na przykład:

x = -5
if x > 0:
    print("x jest dodatnie")
else:
    print("x jest ujemne lub zero")

Ten kod wyświetli "x jest ujemne lub zero" na ekranie, ponieważ warunek `x > 0` jest fałszywy.

Można również użyć wielokrotnych klauzul `elif`, które sprawdzają kolejne warunki, jeśli poprzednie były fałszywe. Na przykład:

x = 0
if x > 0:
    print("x jest dodatnie")
elif x < 0:
    print("x jest ujemne")
else:
    print("x jest równy zero")

Ten kod wyświetli "x jest równy zero" na ekranie, ponieważ warunek `x > 0` jest fałszywy i warunek `x < 0` jest również fałszywy.

- Instrukcja `for` służy do wykonania pewnego bloku kodu określoną liczbę razy lub dla każdego elementu z jakiejś sekwencji. Składnia instrukcji `for` jest następująca:

for zmienna in sekwencja:
    blok kodu

Zmienna jest nazwą, która przyjmuje kolejne wartości z sekwencji. Sekwencja jest obiektem, który zawiera wiele elementów, takich jak lista, krotka, ciąg znaków lub zakres. Blok kodu jest wcięty względem słowa kluczowego `for` i zawiera instrukcje, które mają być wykonane dla każdej wartości zmiennej. Na przykład:

for i in range(5):
    print(i)

Ten kod wyświetli liczby od 0 do 4 na ekranie, ponieważ `range(5)` jest sekwencją liczb całkowitych od 0 do 4, a zmienna `i` przyjmuje kolejno te wartości.

for litera in "Python":
    print(litera)

Ten kod wyświetli litery P, y, t, h, o, n na ekranie, ponieważ "Python" jest sekwencją znaków, a zmienna `litera` przyjmuje kolejno te wartości.

- Instrukcja `while` służy do wykonania pewnego bloku kodu dopóki spełniony jest jakiś warunek. Składnia instrukcji `while` jest następująca:

while warunek:
    blok kodu

Warunek jest wyrażeniem logicznym, które może być prawdziwe (`True`) lub fałszywe (`False`). Blok kodu jest wcięty względem słowa kluczowego `while` i zawiera instrukcje, które mają być wykonane, jeśli warunek jest prawdziwy. Na przykład:

x = 10
while x > 0:
    print(x)
    x = x - 1

Ten kod wyświetli liczby od 10 do 1 na ekranie, ponieważ warunek `x > 0` jest prawdziwy dopóki `x` nie osiągnie wartości 0. W każdym obiegu pętli wartość `x` jest zmniejszana o 1 za pomocą instrukcji `x = x - 1`.

21. Raspberry Pi jest potężnym i elastycznym komputerem, ale ma pewne ograniczenia. Brakuje mu pinów analogowych, dlatego nie radzi sobie dobrze z czujnikami dostarczającymi sygnały analogowe, takimi jak termometry czy czujniki światła. W takich przypadkach lepiej jest użyć mikrokontrolera Arduino, który ma piny analogowe i jest idealny do pracy z czujnikami i urządzeniami analogowymi.

Można podłączyć i sterować Arduino bezpośrednio z komputera, w tym także z Raspberry Pi. Aby to zrobić, należy zainstalować odpowiednie oprogramowanie zarówno na komputerze, jak i na Raspberry Pi. Arduino często działa na kodzie napisanym w języku C, chociaż niektóre modele obsługują inne języki, takie jak Python.

Po zainstalowaniu oprogramowania, można podłączyć Arduino do Raspberry Pi za pomocą kabla USB. Oprogramowanie umożliwia przesyłanie danych między nimi, a także wykonywanie programów na Arduino i odbieranie danych z czujników.

W tej konfiguracji, Arduino może pełnić rolę drugorzędnego kontrolera, zbierając dane z czujników analogowych i przekazując je do Raspberry Pi w celu dalszego przetwarzania. Można również tworzyć kod w Raspberry Pi i przesyłać go do Arduino w celu testowania. Gdy kod jest gotowy, Arduino można odłączyć od Raspberry Pi i zainstalować w docelowej lokalizacji.

22. W przykładzie Smart Home wszystkie urządzenia łączą się z bramą domową (Home Gateway). Brama domowa działa jako koncentrator dla wszystkich urządzeń, zapewniając połączenie przewodowe i bezprzewodowe. To właśnie w bramie domowej tworzony i hostowany jest interfejs internetowy, który pozwala użytkownikom kontrolować i monitorować wszystkie podłączone urządzenia. Przedstawione są również połączenia sieciowe między bramą domową a innymi urządzeniami sieciowymi. Zwróć uwagę, jak brama domowa łączy się z modemem kablowym, który z kolei łączy się ze splitterem. Splitter dzieli sygnał pochodzący od dostawcy usług internetowych (ISP), wysyłając sygnały telewizji kablowej do telewizora i dane do modemu kablowego. Modem kablowy i splitter zapewnia łączność z Internetem dla bramy domowej, a co za tym idzie - dla całego domu.