## SOLID princípy v IoT
#### Prečo aj firmvér potrebuje dobrý dizajn
[Mirek Biňas](https://bletvaska.github.io)
/ [**OSS Conf Žilina 2026**](https://ossconf.fri.uniza.sk/)

notes:
- uz som tu hovoril viackrat na temu Internetu veci, ale pravidelne som hovoril o infrastrukture ako celku
- dnes vsak budem hovorit o koncovych bodoch architektury - o senzoroch a akcnych clenoch

notes:
- dnes vsak budem hovorit o koncovych bodoch architektury - o senzoroch a akcnych clenoch
## Firmvér
> Softvér trvalo uložený v pamäti mikrokontroléra, ktorý priamo riadi jeho hardvér a vykonáva špecifickú funkciu zariadenia. Spustí sa po zapnutí mikrokontroléra.
notes:
- dnes chcem hovorit o tom, akych pravidiel sa drzat pri programovani firmveru na mikrokontroleri
[](https://techwayfit.com/blogs/design-principles/solid-principles/)
## Single Responsibility Principle (SRP)
> A class should have one and only one reason to change.
> -- [Robert C. Martin](https://en.wikipedia.org/wiki/Single-responsibility_principle)
### Výhody
* kód je ľahšie čitateľný a pochopiteľný
* zmena jednej vlastnosti neovplyvní ostatné
* triedy sa dajú testovať izolovane
* jednoduchšie znovupoužitie
## Stavový stroj
celý životný cyklus zariadenia je organizovaný ako stavový stroj

## Návrhový vzor Stav

## Open/Closed Principle (OCP)
> Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
> -- [Bertrand Meyer](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle)
### Výhody
* škálovateľnosť - nový stav / príkaz / zariadenie sa dá pridať bez zmeny aktuálneho kódu
* paralelný vývoj na viacerých triedach bez konfliktu
* kód, ktorý sa nemení, sa nepokazí
## Liskov Substitution Principle (LSP)
> Objects of a superclass should be replacable with objects of its subclasses.
> -- [Barbara Liskov](https://en.wikipedia.org/wiki/Liskov_substitution_principle)

notes:
- predstavme si situaciu, ze robime prave senzor teploty
- aktualna implementacia - pouzivame senzor DHT11

notes:
- potom pride sef a povie, ze ked vymenime senzor, tak rozsah pracovnych teplot bud vacsi, ako ma DHT11
- a dokonca budeme vediet citat aj desatinne hodnoty

notes:
- ale ked ho vymenime za tento, tak to bude lacnejsie a bude mat nizsiu spotrebu
### ...a máme problém
* každý používa iné knižnice
* každý používa inú komunikačnú zbernicu
* každý má iné požiadavky na piny
* potrebujeme ručne upraviť všetky miesta, kde sa používa:
* inicializácia
* meranie údajov
* webové rozhranie
* príkaz v termináli
```python
from machine import Pin
from dht import DHT11
# init sensor
sensor = DHT11(Pin(4))
# measure data
sensor.measure()
# get temperature
temp = sensor.temperature()
print(temp)
```
```python
from machine import ADC, Pin
# init sensor
sensor = ADC(Pin(26))
# read analog value
value = sensor.read_u16()
# convert to voltage
voltage = value * (3.3 / 65535)
# convert voltage to temperature
temp = (voltage - 0.5) * 100
print(temp)
```
```python
import time
from machine import Pin
import onewire, ds18x20
# init sensor
ow = onewire.OneWire(Pin(4))
sensor = ds18x20.DS18X20(ow)
# find sensor
roms = sensor.scan()
# measure temperature
sensor.convert_temp()
# wait for conversion
time.sleep_ms(750)
# get temperature
temp = sensor.read_temp(roms[0])
print(temp)
```
notes:
- pre ilustráciu - takto vyzerajú príslušné fragmenty kódu
### Čo majú všetky tri senzory teploty spoločné?
### Potomok vie nahradiť predka
```python
# predok každého teplotného senzora
class TemperatureSensor:
def temperature(self) -> float:
raise NotImplementedError
```
```python
# implementácia potomka pre DHT11
from machine import Pin
from dht import DHT11
class DHT11(TemperatureSensor):
def __init__(self, pin: int):
self.sensor = DHT11(Pin(pin))
def temperature(self) -> float:
self.sensor.measure()
return self.sensor.temperature()
```
## Komponent
Komponent je **samostatná**, **zapúzdrená jednotka** systému, ktorá má **jasne definované rozhranie** a poskytuje **konkrétnu funkcionalitu**.
## Interface Segregation Principle (ISP)
> Clients should not be forced to depend upon methods that they do not use.
> -- [Robert C. Martin](https://en.wikipedia.org/wiki/Interface_segregation_principle)
### WTF?
* ak by sme mali len DHT11, tak by spoločný predok vyzeral takto:
```python
class SensorDevice:
def temperature(self) -> float:
raise NotImplementedError
def humidity(self) -> float:
raise NotImplementedError
```
### ...a máme problém
* ale TMP36 ani DS1820 nemerajú vlhkosť, takže `humidity()` nepotrebujú
* ale senzor svetla potrebuje `intensity()`, ale nepotrebuje `temperature()` a `humidity()`
* ale senzor tlaku potrebuje `pressure()`, ale nepotrebuje `temperature()`, `humidity()` ani `intensity()`
### Riešenie
* miesto jedného mega-šupa-bomba-špica rozhrania vytvoríme niekoľko menších rozhraní
## Mixins
> Mixin je trieda, ktorá pridáva jednu alebo viacero konkrétnych vlastností alebo správanie inej triede.
## Dependency Inversion Principle (DIP)
> Abstractions should not depend upon details. Details should depend upon abstractions.
> -- [Robert C. Martin](https://en.wikipedia.org/wiki/Dependency_inversion_principle)
### O čo ide?
* vysokoúrovňová logika aplikácie by nemala byť pevne naviazaná na konkrétnu implementáciu, ale na abstrakciu
[](https://techwayfit.com/blogs/design-principles/solid-principles/)
## Prečo SOLID na mikrokontroléroch?
* ak blikáš len LED-kou, tak nemusíš
* jednoduchšia výmena hardvéru - lebo abstrakcia/rozhranie
* lepšia testovateľnosť - zapúzdrené správanie
* jednoduchšia rozšíriteľnosť / škálovateľnosť
* znovupoužiteľnosť kódu
* dobrá tímová práca

(**https://bit.ly/4eXGujh**)