## 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))
[![ESP32](images/esp32.jpg)](https://www.espressif.com/en/products/socs/esp32)
[![MicroPython](images/logo-micropython.jpg)](http://micropython.org)
[![MQTT](images/logo-mqtt.svg)](https://mqtt.org)
## NeoPixel
## NeoPixel je WS2812
![WS2812](images/ws2812.jpg)
## LED pásik s WS2812B
![WS2812B Led Strip](images/ws2812b.led.strip.png)
## Modul WS2812B
![WS2812B Module](images/ws2812b.module.png)
Notes:
* https://freesvg.org/ws2812b-led-strip
![WS2812B Led Strips](images/ws2812b.led.strips.jpg)
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
![Controlling Individual Pixels](images/control.leds.png)
```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
![Clear All Pixels](images/effect-clear.png)
```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
![Set All Pixels to the Same Color](images/effect-set.color.png)
```python
def set_color(pixels, r, g, b):
for i in range(pixels.n):
pixels[i] = (r, g, b)
pixels.write()
```
## Cycle efekt
![Cycle Effect](images/effect-cycle.png)
```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
![Bounce Effect](images/effect-bounce.png)
```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
![How Generators Work?](images/tape.png)
[![Python Generators](images/python.generators.webp)](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
![Warning](images/warning.png)
## Ž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
![qr code](https://api.qrserver.com/v1/create-qr-code/?data=http://bit.ly/2KtBJUa&size=300x300)
(**http://bit.ly/2KtBJUa**)