## Vianočné svetielka
#### alebo ako ovládať vianočné svetlá na diaľku cez MQTT s ESP32
[mirek](https://bletvaska.github.io)
/ [**Namakaný deň - Webináre**](http://www.namakanyden.sk/webinare/)
## Motivácia
## Interaktívny vianočný stromček v SOS
* autor: Matúš Čopík
* riešenie: ESP8266 + Arduino IDE + HTTP server + PHP stránka
* článok: [Technické zákulisie interaktívneho vianočného stromčeka](https://www.sos.sk/articles/sos-supplier-of-solution/technicke-zakulisie-interaktivneho-vianocneho-stromceka-2119) (15.2.2018)
* Namakaný deň 2018: [Ako pripojiť vianočný stromček na internet](http://www.namakanyden.sk/2018/#main-track) ([video](https://archive.tp.cvtisr.sk/?31959103))
[](https://www.espressif.com/en/products/socs/esp32)
[](http://micropython.org)
[](https://mqtt.org)
## NeoPixel
## NeoPixel je WS2812

## LED pásik s WS2812B

## Modul WS2812B

Notes:
* https://freesvg.org/ws2812b-led-strip

Notes:
* https://www.eledsolutions.com/eled-strip-lighting-solutions/
## NeoPixel a uPython
* modul [`neopixel`](https://docs.micropython.org/en/latest/esp8266/tutorial/neopixel.html)
* obsahuje triedu `NeoPixel`
* inicializácia:
```python
from machine import Pin
from neopixel import NeoPixel
np = NeoPixel(Pin(12), 50)
```
## Ovládanie pixelov

```python
from machine import Pin
from neopixel import NeoPixel
np = NeoPixel(Pin(12), 50)
np[0] = (255, 0, 0) # prvy pixel
np[3] = (125, 204, 223)
np[7] = (120, 153, 23)
np[10] = (255, 0, 153)
np[-1] = (0, 0, 255) # posledny pixel
np[np.n // 2] = (0, 255, 0) # prostredny pixel
np.write()
```
## Svetelné efekty
## Zmazanie všetkých pixelov

```python
def clear(pixels):
for i in range(pixels.n):
pixels[i] = (0, 0, 0)
pixels.write()
```
## Nastavenie všetkých pixelov na jednu farbu

```python
def set_color(pixels, r, g, b):
for i in range(pixels.n):
pixels[i] = (r, g, b)
pixels.write()
```
## Cycle efekt

```python
def cycle(pixels, r, g, b, wait):
clear(pixels)
for pos in range(pixels.n):
pixels[pos] = (r, g, b)
pixels.write()
sleep_ms(wait)
pixels[pos] = (0, 0, 0)
else:
pixels.write()
```
## Bounce efekt

```python
def bounce(pixels, r, g, b, wait):
set_color(pixels, r, g, b)
for pos in range(pixels.n):
pixels[pos] = (0, 0, 0)
pixels.write()
sleep_ms(wait // 2)
pixels[pos] = (r, g, b)
pixels.write()
sleep_ms(wait // 2)
for pos in range(pixels.n - 1, -1, -1):
pixels[pos] = (0, 0, 0)
pixels.write()
sleep_ms(wait // 2)
pixels[pos] = (r, g, b)
pixels.write()
sleep_ms(wait // 2)
```
```python
def bounce(pixels, r, g, b, wait):
set_color(pixels, r, g, b)
for i in range(2 * pixels.n - 1):
if (i // pixels.n) % 2 == 0:
pos = i % pixels.n
else:
pos = pixels.n - 1 - (i % pixels.n) - 1
pixels[pos] = (0, 0, 0)
pixels.write()
sleep_ms(wait)
pixels[pos] = (r, g, b)
else:
pixels.write()
```
## And Now for Something Completely Different
## Ďiaľkové ovládanie
cez *Internet* pomocou *MQTT*
## MQTT a uPython
* obsahuje moduly [`umqtt.simple`](https://pypi.org/project/micropython-umqtt.simple/) a [`umqtt.robust`](https://pypi.org/project/micropython-umqtt.robust/) vo verzii *1.0*
* existujú aj novšie verzie *2.0*
* použijeme verejný broker [`broker.hivemq.com`](http://www.mqtt-dashboard.com)
* online [MQTT Websocket client](http://www.hivemq.com/demos/websocket-client/)
* topic pre správy: `iotlab/things/stromcek`
## Pripojenie
```python
from umqtt.robust import MQTTClient
# connect to WiFi
do_connect('ssid', 'password')
# connect to MQTT broker
client = MQTTClient('client-id', 'broker-ip', 1883)
client.set_callback(on_message)
client.connect()
client.subscribe('iotlab/things/stromcek')
while True:
client.wait_msg()
```
## `on_message() Callback`
```python
def on_message(topic, message):
print('>> {}: {}'.format(topic, message))
if message == b'cycle':
cycle(np, 255, 0, 0, 100)
elif message == b'bounce':
bounce(np, 0, 255, 0, 100)
elif message == b'rainbow':
rainbow_cycle(np, 100)
else:
print('>> Error: unknown effect {}!'.format(message))
```
## Houston, we have a problem
## Generátory

[](https://realpython.com/introduction-to-python-generators/)
## Cycle ako Generátor
```python
def cycle(pixels, r, g, b, wait):
clear(pixels)
while True:
for pos in range(pixels.n):
pixels[pos] = (r, g, b)
pixels.write()
sleep_ms(wait)
pixels[pos] = (0, 0, 0)
yield
else:
pixels.write()
```
## Aktualizácia
* zo všetkých efektov spraviť generátory
* nekonečná slučka a `yield`
* aktualizovať `on_message()`
* globálna premenná `animation`
* priradiť jej príslušnú animáciu
* upraviť hlavnú slučku
```python
global animation
animation = bounce(np, 255, 0, 0, 100)
while True:
client.check_msg()
next(animation)
```
## Webové rozhranie

## Živý stream
## Otázky?
Namakaný Newsletter
Ak nechcete, aby vám ušli akcie organizované makačmi okolo Namakaného dňa, odoberajte newsletter. Vždy vám dáme vedieť, keď budeme niečo namakané organizovať.
## Ďalšie zdroje
* [Controlling NeoPixels](https://docs.micropython.org/en/latest/esp8266/tutorial/neopixel.html) - uPython dokumentácia pre modul `neopixel`
* [MicroPython: WS2812B Addressable RGB LEDs with ESP32 and ESP8266](https://randomnerdtutorials.com/micropython-ws2812b-addressable-rgb-leds-neopixel-esp32-esp8266/)
* [Datasheet](http://www.world-semi.com/solution/list-4-1.html) - pre rozličné verzie WS2812
* [webinar.py](webinar.py) - zdrojový kód vytvorený počas webináru
## Poďakovanie
* **Matúš Čopík** - za nápad, podnety, svetielka a pomoc pri realizácii
* **Bianka Rujáková** - za mocnú podobu webovej stránky

(**http://bit.ly/2KtBJUa**)