[PRES] [presentations] master: Confoo IOT talk
[email protected] (Derick Rethans) Mon, 23 Feb 2026 17:04:34 +0000
| Newsgroups | php.pres |
|---|---|
| Message-ID | <[email protected]> |
Author: Derick Rethans (derickr)=0ADate: 2026-02-23T16:59:40Z=0A=0ACommit: = https://github.com/php/presentations/commit/fc118f9042621ad99a6b432ade2e2e1= b982bda95=0ARaw diff: https://github.com/php/presentations/commit/fc118f904= 2621ad99a6b432ade2e2e1b982bda95.diff=0A=0AConfoo IOT talk=0A=0AChanged path= s:=0A A iot-confoo26.xml=0A A slides/iot/.ha-php-mqtt-next-animations.x= ml.swp=0A A slides/iot/MQTT-all.png=0A A slides/iot/chapter-and-then-th= ere-was-light.xml=0A A slides/iot/chapter-desk-control.xml=0A A slides/= iot/chapter-plans-and-trees.xml=0A A slides/iot/chapter-smart-heating.xml= =0A A slides/iot/esp32-code.png=0A A slides/iot/esp32-lego-box.png=0A = A slides/iot/esp32-schematic.png=0A A slides/iot/esp32-vga-palette.png= =0A A slides/iot/go-streamdeck-code.xml=0A A slides/iot/go-streamdeck-c= onfiguration.xml=0A A slides/iot/go-streamdeck-publish-mqtt.xml=0A A sl= ides/iot/ha-action-turn-lights-off-bright.png=0A A slides/iot/ha-action-t= urn-lights-off.png=0A A slides/iot/ha-action-turn-lights-on-dark.png=0A = A slides/iot/ha-action-turn-lights-on-enter.png=0A A slides/iot/ha-actio= ns-turn-lights-on.png=0A A slides/iot/ha-add-mqtt-integration.xml=0A A = slides/iot/ha-create-forecast-mqtt-trigger.xml=0A A slides/iot/ha-create-= mqtt-trigger.xml=0A A slides/iot/ha-dim-lights-action.png=0A A slides/i= ot/ha-forecast.png=0A A slides/iot/ha-forecast.xml=0A A slides/iot/ha-l= uminance-both.png=0A A slides/iot/ha-luminance-non-smooth.png=0A A slid= es/iot/ha-nest-data-1.xml=0A A slides/iot/ha-nest-data-2.xml=0A A slide= s/iot/ha-nest-data-mqtt-result.xml=0A A slides/iot/ha-nest-data-mqtt-step= 0.xml=0A A slides/iot/ha-nest-data-mqtt-step2.xml=0A A slides/iot/ha-ne= st-data-mqtt-step3.xml=0A A slides/iot/ha-nest-data-mqtt-step4.xml=0A A = slides/iot/ha-nest-data-mqtt.xml=0A A slides/iot/ha-nest-data.xml=0A A = slides/iot/ha-nest-heat-slope1.png=0A A slides/iot/ha-nest-heat-slope2.p= ng=0A A slides/iot/ha-nest-schedule-alone.png=0A A slides/iot/ha-nest-s= chedule.png=0A A slides/iot/ha-nest-schedule.xml=0A A slides/iot/ha-nes= t-slope-0.jpeg=0A A slides/iot/ha-nest-slope-1.jpeg=0A A slides/iot/ha-= nest-slope-2.jpeg=0A A slides/iot/ha-nest-slope.xcf=0A A slides/iot/ha-= nest-slope1.png=0A A slides/iot/ha-nest-slope2.png=0A A slides/iot/ha-n= est-temperature.png=0A A slides/iot/ha-php-mqtt-code-rgb.xml=0A A slide= s/iot/ha-php-mqtt-code.xml=0A A slides/iot/ha-php-mqtt-lego-box-design.xm= l=0A A slides/iot/ha-php-mqtt-lego-box-prototype.xml=0A A slides/iot/ha= -php-mqtt-next-animations.xml=0A A slides/iot/ha-php-mqtt-result-rainy.xm= l=0A A slides/iot/ha-php-mqtt-result-sunny.xml=0A A slides/iot/ha-php-m= qtt-result-unknown.xml=0A A slides/iot/ha-php-mqtt-result.xml=0A A slid= es/iot/ha-php-mqtt.xml=0A A slides/iot/ha-program-esp32-board.xml=0A A = slides/iot/ha-sensor-current-temp1.png=0A A slides/iot/ha-sensor-current-= temp2.png=0A A slides/iot/ha-smooth-brightness.png=0A A slides/iot/ha-t= ree-lights.png=0A A slides/iot/ha-zigbee-network.png=0A A slides/iot/he= ating-rate.png=0A A slides/iot/heating-schedule.png=0A A slides/iot/hom= e-assistant-1.xml=0A A slides/iot/icons.png=0A A slides/iot/iot-elephpa= nt-shelf.jpeg=0A A slides/iot/iot-esp32-matrix.jpeg=0A A slides/iot/iot= -homeassistant-zigbee.jpeg=0A A slides/iot/iot-homeassistant.jpeg=0A A = slides/iot/iot-human-detector.jpeg=0A A slides/iot/iot-lamp-dim.gif=0A A= slides/iot/iot-lego-lights.jpeg=0A A slides/iot/iot-matrix-sun-paper.jp= eg=0A A slides/iot/iot-monty.jpeg=0A A slides/iot/iot-motion-detector.j= peg=0A A slides/iot/iot-smartlife-plug.jpeg=0A A slides/iot/iot-streamd= eck-home.jpeg=0A A slides/iot/iot-streamdeck-obs.jpeg=0A A slides/iot/i= ot-weather-lego-prototype.jpeg=0A A slides/iot/iot-weather-lego-prototype= .jpeg.jpeg=0A A slides/iot/iot-weather-rainy.jpeg=0A A slides/iot/iot-w= eather-sunny.jpeg=0A A slides/iot/iot-weather-unknown.jpeg=0A A slides/= iot/iot-wedding-tree-switch.jpeg=0A A slides/iot/iot-wedding-tree.jpeg=0A= A slides/iot/lights-options.png=0A A slides/iot/livingroom-ok.xml=0A = A slides/iot/livingroom-party.xml=0A A slides/iot/monty.xml=0A A slide= s/iot/mqtt-integration.png=0A A slides/iot/mqtt-logo.svg=0A A slides/io= t/mqtt-project-goal.xml=0A A slides/iot/mqtt-whats-next-elephpants.xml=0A= A slides/iot/mqtt-whats-next-esp32-board.xml=0A A slides/iot/mqtt-what= s-next-lego.xml=0A A slides/iot/mqtt-whats-next-weather-matrix.xml=0A A = slides/iot/mqtt-whats-next.xml=0A A slides/iot/mqtt.xml=0A A slides/io= t/office-lights-dim.xml=0A A slides/iot/office-lights-goals.xml=0A A sl= ides/iot/office-lights-turn-off-bright-enough.xml=0A A slides/iot/office-= lights-turn-off-leave.xml=0A A slides/iot/office-lights-turn-on.xml=0A A= slides/iot/party-lights.gif=0A A slides/iot/smart-plug-1.xml=0A A sli= des/iot/streamdeck.xml=0A A slides/iot/the_internet_from_the_it_crowd.jpe= g=0A A slides/iot/varying-light-smoothed.xml=0A A slides/iot/varying-li= ght.xml=0A A slides/iot/wishing-tree.xml=0A A slides/iot/zigbee-network= .xml=0A A templates/default/sub.ezt=0A=0A=0ADiff:=0A=0Adiff --git a/iot-c= onfoo26.xml b/iot-confoo26.xml=0Anew file mode 100644=0Aindex 00000000..d02= 180bf=0A--- /dev/null=0A+++ b/iot-confoo26.xml=0A@@ -0,0 +1,99 @@=0A+<?xml = version=3D"1.0" encoding=3D"utf-8"?>=0A+<presentation css=3D"derick.css">= =0A+<topic>IOT</topic>=0A+<title>Automating My House with PHP & Go</tit= le>=0A+<event>ConFoo 2026</event>=0A+<location>Montr=C3=A9al, Canada</locat= ion>=0A+<date>Feb 26th, 2026</date>=0A+<speaker>Derick Rethans</speaker>=0A= +<email>[email protected]</email>=0A+<mastodon>@[email protected]</= mastodon>=0A+<twitter>derickr</twitter>=0A+<url>https://derickrethans.nl/ta= lks/iot-confoo26</url>=0A+<joindin>https://derickrethans.nl</joindin>=0A+<s= lide>slides/xdebug/title.xml</slide>=0A+<slide>slides/mongodb/me.xml</slide= >=0A+=0A+Chapter 1: Plants and Trees=0A+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A+=0A+<= slide>slides/iot/chapter-plans-and-trees.xml</slide>=0A+=0A+<slide>slides/i= ot/monty.xml</slide>=0A+<slide>slides/iot/smart-plug-1.xml</slide>=0A+<slid= e>slides/iot/home-assistant-1.xml</slide>=0A+<slide>slides/iot/zigbee-netwo= rk.xml</slide>=0A+<slide>slides/iot/wishing-tree.xml</slide>=0A+=0A+Chapter= 2: And Then There Was Light=0A+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A+=0A+<sli= de>slides/iot/chapter-and-then-there-was-light.xml</slide>=0A+=0A+<slide>sl= ides/iot/varying-light.xml</slide>=0A+<slide>slides/iot/office-lights-goals= .xml</slide>=0A+<slide>slides/iot/office-lights-turn-off-leave.xml</slide>= =0A+<slide>slides/iot/office-lights-turn-off-bright-enough.xml</slide>=0A+<= slide>slides/iot/varying-light-smoothed.xml</slide>=0A+<slide>slides/iot/of= fice-lights-turn-on.xml</slide>=0A+<slide>slides/iot/office-lights-dim.xml<= /slide>=0A+=0A+<slide>slides/iot/livingroom-party.xml</slide>=0A+<slide>sli= des/iot/livingroom-ok.xml</slide>=0A+=0A+Chapter 3: Desk Control=0A+=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A+=0A+<sli= de>slides/iot/chapter-desk-control.xml</slide>=0A+<slide>slides/iot/streamd= eck.xml</slide>=0A+<slide>slides/iot/mqtt-project-goal.xml</slide>=0A+<slid= e>slides/iot/mqtt.xml</slide>=0A+<slide>slides/iot/ha-add-mqtt-integration.= xml</slide>=0A+<slide>slides/iot/ha-create-mqtt-trigger.xml</slide>=0A+<sli= de>slides/iot/go-streamdeck-configuration.xml</slide>=0A+<slide>slides/iot/= go-streamdeck-code.xml</slide>=0A+<slide>slides/iot/go-streamdeck-publish-m= qtt.xml</slide>=0A+=0A+Chapter 4: Blinking Lights=0A+=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A+=0A+<slide>= slides/iot/ha-forecast.xml</slide>=0A+=0A+<slide>slides/iot/ha-create-forec= ast-mqtt-trigger.xml</slide>=0A+<slide>slides/iot/ha-program-esp32-board.xm= l</slide>=0A+<slide>slides/iot/mqtt-whats-next-esp32-board.xml</slide>=0A+<= slide>slides/iot/ha-php-mqtt.xml</slide>=0A+<slide>slides/iot/ha-php-mqtt-c= ode.xml</slide>=0A+<slide>slides/iot/ha-php-mqtt-result-unknown.xml</slide>= =0A+<slide>slides/iot/ha-php-mqtt-result-rainy.xml</slide>=0A+<slide>slides= /iot/ha-php-mqtt-code-rgb.xml</slide>=0A+<slide>slides/iot/ha-php-mqtt-resu= lt-sunny.xml</slide>=0A+<slide>slides/iot/ha-php-mqtt-lego-box-prototype.xm= l</slide>=0A+<slide>slides/iot/ha-php-mqtt-lego-box-design.xml</slide>=0A+<= slide>slides/iot/ha-php-mqtt-next-animations.xml</slide>=0A+=0A+Chapter 5: = Smart Heating?=0A+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=0A+=0A+<slide>slides/iot/chapter-smart-heating.xml</slid= e>=0A+<slide>slides/iot/ha-nest-schedule.xml</slide>=0A+<slide>slides/iot/h= a-nest-data.xml</slide>=0A+<slide>slides/iot/ha-nest-data-1.xml</slide>=0A+= <slide>slides/iot/ha-nest-data-2.xml</slide>=0A+<slide>slides/iot/ha-nest-d= ata-mqtt.xml</slide>=0A+<slide>slides/iot/ha-nest-data-mqtt-step0.xml</slid= e>=0A+<slide>slides/iot/ha-nest-data-mqtt-step2.xml</slide>=0A+<slide>slide= s/iot/ha-nest-data-mqtt-step3.xml</slide>=0A+<slide>slides/iot/ha-nest-data= -mqtt-result.xml</slide>=0A+=0A+=0A+Conclusion=0A+=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=0A+=0A+<slide>slides/iot/mqtt-whats-next-elephpants.xml</slide>=0A+<= slide>slides/iot/mqtt-whats-next-lego.xml</slide>=0A+=0A+<slide>slides/mong= odb/questions.xml</slide>=0A+<slide>slides/xdebug/resources.xml</slide>=0A+= =0A+</presentation>=0Adiff --git a/slides/iot/.ha-php-mqtt-next-animations.= xml.swp b/slides/iot/.ha-php-mqtt-next-animations.xml.swp=0Anew file mode 1= 00644=0Aindex 00000000..6165d690=0ABinary files /dev/null and b/slides/iot/= .ha-php-mqtt-next-animations.xml.swp differ=0Adiff --git a/slides/iot/MQTT-= all.png b/slides/iot/MQTT-all.png=0Anew file mode 100644=0Aindex 00000000..= 994fa424=0ABinary files /dev/null and b/slides/iot/MQTT-all.png differ=0Adi= ff --git a/slides/iot/chapter-and-then-there-was-light.xml b/slides/iot/cha= pter-and-then-there-was-light.xml=0Anew file mode 100644=0Aindex 00000000..= 96f9c994=0A--- /dev/null=0A+++ b/slides/iot/chapter-and-then-there-was-ligh= t.xml=0A@@ -0,0 +1,3 @@=0A+<slide style=3D"title">=0A+<title>Chapter 2: And= Then There Was Light</title>=0A+</slide>=0Adiff --git a/slides/iot/chapter= -desk-control.xml b/slides/iot/chapter-desk-control.xml=0Anew file mode 100= 644=0Aindex 00000000..590432aa=0A--- /dev/null=0A+++ b/slides/iot/chapter-d= esk-control.xml=0A@@ -0,0 +1,3 @@=0A+<slide style=3D"title" background=3D"i= ot-streamdeck-home.jpeg">=0A+<title>Chapter 3: Desk Control</title>=0A+</sl= ide>=0Adiff --git a/slides/iot/chapter-plans-and-trees.xml b/slides/iot/cha= pter-plans-and-trees.xml=0Anew file mode 100644=0Aindex 00000000..f1530826= =0A--- /dev/null=0A+++ b/slides/iot/chapter-plans-and-trees.xml=0A@@ -0,0 += 1,4 @@=0A+<slide style=3D"title">=0A+<title>Chapter 1: Plants and Trees</ti= tle>=0A+</slide>=0A+=0Adiff --git a/slides/iot/chapter-smart-heating.xml b/= slides/iot/chapter-smart-heating.xml=0Anew file mode 100644=0Aindex 0000000= 0..1db50815=0A--- /dev/null=0A+++ b/slides/iot/chapter-smart-heating.xml=0A= @@ -0,0 +1,4 @@=0A+<slide style=3D"title" background=3D"lights-options.png"= >=0A+<title><br/><br/>Chapter 5: Smart Heating |777777|?|<br/><br/><br/>= 60;</title>=0A+<image filename=3D"ha-nest-schedule-alone.png"/>=0A+</slide>= =0Adiff --git a/slides/iot/esp32-code.png b/slides/iot/esp32-code.png=0Anew= file mode 100644=0Aindex 00000000..f7e52697=0ABinary files /dev/null and b= /slides/iot/esp32-code.png differ=0Adiff --git a/slides/iot/esp32-lego-box.= png b/slides/iot/esp32-lego-box.png=0Anew file mode 100644=0Aindex 00000000= ..caef7f08=0ABinary files /dev/null and b/slides/iot/esp32-lego-box.png dif= fer=0Adiff --git a/slides/iot/esp32-schematic.png b/slides/iot/esp32-schema= tic.png=0Anew file mode 100644=0Aindex 00000000..8b0874f1=0ABinary files /d= ev/null and b/slides/iot/esp32-schematic.png differ=0Adiff --git a/slides/i= ot/esp32-vga-palette.png b/slides/iot/esp32-vga-palette.png=0Anew file mode= 100644=0Aindex 00000000..e4923fb9=0ABinary files /dev/null and b/slides/io= t/esp32-vga-palette.png differ=0Adiff --git a/slides/iot/go-streamdeck-code= .xml b/slides/iot/go-streamdeck-code.xml=0Anew file mode 100644=0Aindex 000= 00000..e421a6fd=0A--- /dev/null=0A+++ b/slides/iot/go-streamdeck-code.xml= =0A@@ -0,0 +1,67 @@=0A+<slide style=3D"title">=0A+<blurb class=3D"large">St= ep 4: Make Stream Deck Listen for Incoming MQTT Messages</blurb>=0A+<break/= >=0A+<example inline=3D"2">=0A+import (=0A+ mqtt "github.com/eclipse/paho.= mqtt.golang"=0A+ "github.com/spf13/viper"=0A+)=0A+=0A+type MqttThing struc= t {=0A+ SD *streamdeck.StreamDeck=0A+ Brightness *Brightness=0A= + mqtt_client mqtt.Client=0A+ actions []MqttAction=0A+}=0A+=0A+type M= qttSubscription struct {=0A+ Topic string `mapstructure:"topic"`=0A+}=0A+= =0A+type MqttAction struct {=0A+ Topic string `mapstructure:"top= ic"`=0A+ Value string `mapstructure:"value"`=0A+ Type = string `mapstructure:"type"`=0A+ BrightnessLevel *int `mapstructure:"b= rightnessLevel"`=0A+}=0A+=0A+func (p *MqttThing) onMqttMessageReceived(clie= nt mqtt.Client, message mqtt.Message) {=0A+ payload :=3D string(message.Pa= yload()[:])=0A+=0A+ for _, topic :=3D range p.actions {=0A+ if topic.To= pic =3D=3D message.Topic() && topic.Value =3D=3D payload {=0A+ = if topic.Type =3D=3D "brightness" && topic.BrightnessLevel !=3D ni= l {=0A+ p.Brightness.SetBrightnessLevel(*topic.BrightnessLevel)=0A+ = }=0A+ }=0A+ }=0A+}=0A+=0A+func (p *MqttThing) Init() {=0A+ opts := =3D mqtt.NewClientOptions().=0A+ AddBroker(viper.GetString("mqtt.broker"= )).=0A+ SetClientID(viper.GetString("mqtt.clientid")).=0A+ SetUsernam= e(viper.GetString("mqtt.username")).=0A+ SetPassword(viper.GetString("mq= tt.password"))=0A+=0A+ viper.UnmarshalKey("mqtt.actions", &p.actions)= =0A+=0A+ opts.OnConnect =3D func(c mqtt.Client) {=0A+ var subscriptions= []MqttSubscription=0A+ viper.UnmarshalKey("mqtt.subscriptions", &su= bscriptions)=0A+=0A+ for _, topic :=3D range subscriptions {=0A+ if= token :=3D p.mqtt_client.Subscribe(topic.Topic, byte(0), p.onMqttMessageRe= ceived);=0A+ token.Wait() && token.Error() !=3D nil {=0A+ = panic(token.Error())=0A+ }=0A+ }=0A+ }=0A+=0A+ p.mqtt_client = =3D mqtt.NewClient(opts)=0A+ if conn_token :=3D p.mqtt_client.Connect(); c= onn_token.Wait() && conn_token.Error() !=3D nil {=0A+ log.Warn()= .Err(conn_token.Error()).Msg("Cannot connect to MQTT")=0A+ }=0A+}=0A+</exa= mple>=0A+</slide>=0Adiff --git a/slides/iot/go-streamdeck-configuration.xml= b/slides/iot/go-streamdeck-configuration.xml=0Anew file mode 100644=0Ainde= x 00000000..1c8a319b=0A--- /dev/null=0A+++ b/slides/iot/go-streamdeck-confi= guration.xml=0A@@ -0,0 +1,25 @@=0A+<slide style=3D"title">=0A+<blurb class= =3D"large">Step 3: Set Up the MQTT Integration for Stream Deck</blurb>=0A+<= break/>=0A+<example inline=3D"2">=0A+ # MQTT Integration=0A+ mqtt:=0A= + broker: "tcp://192.168.42.213:1883"=0A+ clientid: "go-streamdec= k"=0A+ username: "mqtt"=0A+ password: "homeassistant-mqtt-XXXXXXX= "=0A+ subscriptions:=0A+ - topic: *"entities/+/state_change"*=0A+= actions:=0A+ - topic: *"entities/human_detector/state_change"*= =0A+ value: *on|off*=0A+ *type: brightness*=0A+ bright= nessLevel: 0=0A+ - topic: "entities/human_detector/state_change"=0A+ = type: brightness=0A+ value: off|on=0A+ brightnessLevel:= 1=0A+</example>=0A+=0A+<blurb class=3D"center">Subscriptions vs Actions</b= lurb>=0A+</slide>=0Adiff --git a/slides/iot/go-streamdeck-publish-mqtt.xml = b/slides/iot/go-streamdeck-publish-mqtt.xml=0Anew file mode 100644=0Aindex = 00000000..9b770e71=0A--- /dev/null=0A+++ b/slides/iot/go-streamdeck-publish= -mqtt.xml=0A@@ -0,0 +1,28 @@=0A+<slide style=3D"title">=0A+<blurb class=3D"= large">Step 5: Publish to MQTT</blurb>=0A+<break/>=0A+<blurb>Configuration:= </blurb>=0A+<example inline=3D"2">=0A+HousePage:=0A+ - Index: 0=0A+ Typ= e: mqtt-color=0A+ Arguments:=0A+ - StateId: office-lights=0A+ - = Name: "LIGHT"=0A+ - PublishTopic: "homeautomation/office"=0A+ - Act= ivePublishPayload: "light"=0A+ - InactivePublishPayload: "dark"=0A+ = - ActiveStateColor: "#00ff00"=0A+ - InactiveStateColor: "#ff0000"=0A+<= /example>=0A+<break/>=0A+=0A+<blurb>To publish to MQTT:</blurb>=0A+<example= inline=3D"2">=0A+mq.mqtt.mqtt_client.Publish(mq.PublishTopic, 0, false, mq= .NextPublishPayload)=0A+</example>=0A+=0A+<break/>=0A+<blurb>Hooking it int= o the Streamdeck-Goui code was trickier=E2=80=A6</blurb>=0A+=0A+</slide>=0A= diff --git a/slides/iot/ha-action-turn-lights-off-bright.png b/slides/iot/h= a-action-turn-lights-off-bright.png=0Anew file mode 100644=0Aindex 00000000= ..3a0bdbb4=0ABinary files /dev/null and b/slides/iot/ha-action-turn-lights-= off-bright.png differ=0Adiff --git a/slides/iot/ha-action-turn-lights-off.p= ng b/slides/iot/ha-action-turn-lights-off.png=0Anew file mode 100644=0Ainde= x 00000000..ef5acc69=0ABinary files /dev/null and b/slides/iot/ha-action-tu= rn-lights-off.png differ=0Adiff --git a/slides/iot/ha-action-turn-lights-on= -dark.png b/slides/iot/ha-action-turn-lights-on-dark.png=0Anew file mode 10= 0644=0Aindex 00000000..083c389e=0ABinary files /dev/null and b/slides/iot/h= a-action-turn-lights-on-dark.png differ=0Adiff --git a/slides/iot/ha-action= -turn-lights-on-enter.png b/slides/iot/ha-action-turn-lights-on-enter.png= =0Anew file mode 100644=0Aindex 00000000..29a02d48=0ABinary files /dev/null= and b/slides/iot/ha-action-turn-lights-on-enter.png differ=0Adiff --git a/= slides/iot/ha-actions-turn-lights-on.png b/slides/iot/ha-actions-turn-light= s-on.png=0Anew file mode 100644=0Aindex 00000000..d40583fa=0ABinary files /= dev/null and b/slides/iot/ha-actions-turn-lights-on.png differ=0Adiff --git= a/slides/iot/ha-add-mqtt-integration.xml b/slides/iot/ha-add-mqtt-integrat= ion.xml=0Anew file mode 100644=0Aindex 00000000..36424977=0A--- /dev/null= =0A+++ b/slides/iot/ha-add-mqtt-integration.xml=0A@@ -0,0 +1,6 @@=0A+<slide= style=3D"title">=0A+<blurb class=3D"large">Step 1: Add MQTT Integration to= Home Assistant</blurb>=0A+<break/>=0A+<image filename=3D"mqtt-integration.= png"/>=0A+<blurb class=3D"center">%https://www.home-assistant.io/integratio= ns/mqtt%</blurb>=0A+</slide>=0Adiff --git a/slides/iot/ha-create-forecast-m= qtt-trigger.xml b/slides/iot/ha-create-forecast-mqtt-trigger.xml=0Anew file= mode 100644=0Aindex 00000000..a6def605=0A--- /dev/null=0A+++ b/slides/iot/= ha-create-forecast-mqtt-trigger.xml=0A@@ -0,0 +1,23 @@=0A+<slide style=3D"t= itle">=0A+<blurb class=3D"large">Step 1: Create MQTT Trigger in Home Assist= ant</blurb>=0A+<break/>=0A+<example>=0A+alias: Forecast Changes=0A+descript= ion: ""=0A+triggers:=0A+ - trigger: state=0A+ entity_id:=0A+ - wea= ther.forecast_home=0A+conditions: []=0A+actions:=0A+ - action: mqtt.publis= h=0A+ metadata: {}=0A+ data:=0A+ qos: 0=0A+ topic: homeauto= mation/forecast=0A+ payload: "{{trigger.to_state.state}}"=0A+mode: sin= gle=0A+</example>=0A+=0A+<blurb class=3D"center">The payload contains the n= ew (current) state.</blurb>=0A+</slide>=0Adiff --git a/slides/iot/ha-create= -mqtt-trigger.xml b/slides/iot/ha-create-mqtt-trigger.xml=0Anew file mode 1= 00644=0Aindex 00000000..871a2172=0A--- /dev/null=0A+++ b/slides/iot/ha-crea= te-mqtt-trigger.xml=0A@@ -0,0 +1,25 @@=0A+<slide style=3D"title">=0A+<blurb= class=3D"large">Step 2: Create MQTT Trigger in Home Assistant</blurb>=0A+<= break/>=0A+<example>=0A+alias: MQTT Trigger for Presence Sensor=0A+descript= ion: ""=0A+triggers:=0A+ - trigger: state=0A+=09entity_id:=0A+=09 - binar= y_sensor.human_detector=0A+conditions: []=0A+actions:=0A+ - action: mqtt.p= ublish=0A+=09metadata: {}=0A+=09data:=0A+=09 evaluate_payload: false=0A+= =09 qos: 0=0A+=09 retain: false=0A+=09 topic: entities/{{trigger.to_stat= e.object_id}}/state_change=0A+=09 payload: "{{trigger.from_state.state}}|{= {trigger.to_state.state}}"=0A+mode: single=0A+</example>=0A+=0A+<blurb clas= s=3D"center">The payload contains the old and new state.</blurb>=0A+</slide= >=0Adiff --git a/slides/iot/ha-dim-lights-action.png b/slides/iot/ha-dim-li= ghts-action.png=0Anew file mode 100644=0Aindex 00000000..189ca1a7=0ABinary = files /dev/null and b/slides/iot/ha-dim-lights-action.png differ=0Adiff --g= it a/slides/iot/ha-forecast.png b/slides/iot/ha-forecast.png=0Anew file mod= e 100644=0Aindex 00000000..ebfe0026=0ABinary files /dev/null and b/slides/i= ot/ha-forecast.png differ=0Adiff --git a/slides/iot/ha-forecast.xml b/slide= s/iot/ha-forecast.xml=0Anew file mode 100644=0Aindex 00000000..af9d7e7a=0A-= -- /dev/null=0A+++ b/slides/iot/ha-forecast.xml=0A@@ -0,0 +1,3 @@=0A+<slide= style=3D"title" background=3D"iot-matrix-sun-paper.jpeg">=0A+<title>Chapte= r 4: Displaying The Weather</title>=0A+</slide>=0Adiff --git a/slides/iot/h= a-luminance-both.png b/slides/iot/ha-luminance-both.png=0Anew file mode 100= 644=0Aindex 00000000..6b3c104a=0ABinary files /dev/null and b/slides/iot/ha= -luminance-both.png differ=0Adiff --git a/slides/iot/ha-luminance-non-smoot= h.png b/slides/iot/ha-luminance-non-smooth.png=0Anew file mode 100644=0Aind= ex 00000000..915266f1=0ABinary files /dev/null and b/slides/iot/ha-luminanc= e-non-smooth.png differ=0Adiff --git a/slides/iot/ha-nest-data-1.xml b/slid= es/iot/ha-nest-data-1.xml=0Anew file mode 100644=0Aindex 00000000..e435fe4b= =0A--- /dev/null=0A+++ b/slides/iot/ha-nest-data-1.xml=0A@@ -0,0 +1 @@=0A+<= slide background=3D"ha-nest-slope-1.jpeg"/>=0Adiff --git a/slides/iot/ha-ne= st-data-2.xml b/slides/iot/ha-nest-data-2.xml=0Anew file mode 100644=0Ainde= x 00000000..810b7e0e=0A--- /dev/null=0A+++ b/slides/iot/ha-nest-data-2.xml= =0A@@ -0,0 +1,19 @@=0A+<slide background=3D"ha-nest-slope-2.jpeg">=0A+=0A+<= div class=3D"left-side">=0A+<break lines=3D"4"/>=0A+<div class=3D"light-bg"= >=0A+<blurb>Collect:</blurb>=0A+<div effect=3D"fade-in">=0A+<list><bullet>W= hen Nest Turns On and Off</bullet></list>=0A+</div>=0A+<div effect=3D"fade-= in">=0A+<list><bullet>Current Livingroom Temperature</bullet></list>=0A+</d= iv>=0A+<div effect=3D"fade-in">=0A+<list><bullet>Current Outside Temperatur= e</bullet></list>=0A+</div>=0A+</div>=0A+</div>=0A+=0A+</slide>=0Adiff --gi= t a/slides/iot/ha-nest-data-mqtt-result.xml b/slides/iot/ha-nest-data-mqtt-= result.xml=0Anew file mode 100644=0Aindex 00000000..6163a90a=0A--- /dev/nul= l=0A+++ b/slides/iot/ha-nest-data-mqtt-result.xml=0A@@ -0,0 +1,9 @@=0A+<sli= de>=0A+<title>Result=E2=80=BD</title>=0A+=0A+<image filename=3D"heating-rat= e.png"/>=0A+=0A+<div effect=3D"fade-in">=0A+<blurb class=3D"big-centre">INC= ONCLUSIVE</blurb>=0A+</div>=0A+</slide>=0Adiff --git a/slides/iot/ha-nest-d= ata-mqtt-step0.xml b/slides/iot/ha-nest-data-mqtt-step0.xml=0Anew file mode= 100644=0Aindex 00000000..59ae94c9=0A--- /dev/null=0A+++ b/slides/iot/ha-ne= st-data-mqtt-step0.xml=0A@@ -0,0 +1,13 @@=0A+<slide>=0A+<title>Step 0: Crea= te Current Temperature Sensor</title>=0A+=0A+<break lines=3D"2"/>=0A+=0A+<d= iv effect=3D"fade-out">=0A+<image filename=3D"ha-sensor-current-temp1.png"/= >=0A+</div>=0A+=0A+<div effect=3D"fade-in">=0A+<image filename=3D"ha-sensor= -current-temp2.png"/>=0A+</div>=0A+</slide>=0Adiff --git a/slides/iot/ha-ne= st-data-mqtt-step2.xml b/slides/iot/ha-nest-data-mqtt-step2.xml=0Anew file = mode 100644=0Aindex 00000000..de00fd94=0A--- /dev/null=0A+++ b/slides/iot/h= a-nest-data-mqtt-step2.xml=0A@@ -0,0 +1,27 @@=0A+<slide style=3D"title">=0A= +<blurb class=3D"large">Step 2: Create PHP Script to Import Into Database</= blurb>=0A+<example><![CDATA[<?php=0A+$mqtt->subscribe('tempwise/+/state_cha= nge', function($topic, $msg, $ret, $matchWild) use ($c) {=0A+=09if ( ! preg= _match( '@^tempwise/(.*)/state_change$@', $topic, $matchedTopic)) {=0A+=09= =09return;=0A+=09}=0A+=09$topic =3D $matchedTopic[1];=0A+=0A+=09$valueParts= =3D explode( '|', $msg);=0A+=09$value =3D array_last($valueParts);=0A+=0A+= =09$value =3D match($value) {=0A+=09=09'on' =3D> true,=0A+=09=09'off' =3D> = false,=0A+=09=09default =3D> (double) $value,=0A+=09};=0A+=0A+=09$doc =3D [= =0A+=09=09'ts' =3D> new MongoDB\BSON\UTCDateTime(),=0A+=09=09't' =3D> $topi= c,=0A+=09=09'v' =3D> $value,=0A+=09];=0A+=0A+=09$result =3D $c->insertOne($= doc);=0A+}, 0);]]></example>=0A+</slide>=0Adiff --git a/slides/iot/ha-nest-= data-mqtt-step3.xml b/slides/iot/ha-nest-data-mqtt-step3.xml=0Anew file mod= e 100644=0Aindex 00000000..6a7ae651=0A--- /dev/null=0A+++ b/slides/iot/ha-n= est-data-mqtt-step3.xml=0A@@ -0,0 +1,40 @@=0A+<slide background=3D"ha-nest-= slope-2.jpeg">=0A+<title>Step 3: Calculate Heating Rate</title>=0A+<div cla= ss=3D"left-side">=0A+<div class=3D"light-bg">=0A+=0A+<div effect=3D"fade-in= ">=0A+<list><bullet>Loop over all elements for %nest% events</bullet></list= >=0A+</div>=0A+=0A+<div effect=3D"fade-in">=0A+<list><bullet>Find closest l= ivingroom temperature before and after</bullet></list>=0A+</div>=0A+=0A+<di= v effect=3D"fade-in">=0A+<list><bullet>Temperature(s) at Nest on/off points= :<br/>=0A+~=CE=94T~ =3D =CE=94T<sub>1</sub> - =CE=94T<sub>0</sub><br/>=0A+~= =CE=94t~ =3D =CE=94t<sub>1</sub> - =CE=94t<sub>0</sub><br/>=0A+~x~ =3D t<su= b>nest</sub> - t<sub>0</sub><br/>=0A+~T~<sub>nest</sub> =3D ((x / =CE=94t) = * =CE=94T) + =CE=94T<sub>0</sub> *=C2=B0C*=0A+</bullet></list>=0A+</div>=0A= +=0A+<div effect=3D"fade-in">=0A+<list><bullet>Rate between Nest on/off poi= nts:<br/>=0A+~=CE=94T~ =3D T<sub>off</sub> - T<sub>on</sub><br/>=0A+~=CE= =94t~ =3D t<sub>off</sub> - t<sub>on</sub><br/>=0A+=0A+~rate~ =3D =CE=94T /= =CE=94t *=C2=B0C / second*<br/>=0A+</bullet></list>=0A+</div>=0A+=0A+<div = effect=3D"fade-in">=0A+<list><bullet>Average Outside Temperature:<br/>=0A+= =CE=94T<sub>outside</sub> =3D (T<sub>outside,0</sub> + T<sub>outside,1</sub= >) / 2 *=C2=B0C*=0A+</bullet></list>=0A+</div>=0A+=0A+</div>=0A+</div>=0A+<= /slide>=0Adiff --git a/slides/iot/ha-nest-data-mqtt-step4.xml b/slides/iot/= ha-nest-data-mqtt-step4.xml=0Anew file mode 100644=0Aindex 00000000..6c6f5b= 43=0A--- /dev/null=0A+++ b/slides/iot/ha-nest-data-mqtt-step4.xml=0A@@ -0,0= +1,19 @@=0A+<slide>=0A+=0A+<div class=3D"left-side">=0A+<break lines=3D"4"= />=0A+<div class=3D"light-bg">=0A+<blurb>Collect:</blurb>=0A+<div effect=3D= "fade-in">=0A+<list><bullet>When Nest Turns On and Off</bullet></list>=0A+<= /div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>Current Livingroom Tempe= rature</bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bull= et>Current Outside Temperature</bullet></list>=0A+</div>=0A+</div>=0A+</div= >=0A+=0A+</slide>=0Adiff --git a/slides/iot/ha-nest-data-mqtt.xml b/slides/= iot/ha-nest-data-mqtt.xml=0Anew file mode 100644=0Aindex 00000000..c03377ee= =0A--- /dev/null=0A+++ b/slides/iot/ha-nest-data-mqtt.xml=0A@@ -0,0 +1,25 @= @=0A+<slide style=3D"title">=0A+<blurb class=3D"large">Step 1: Create MQTT = Trigger in Home Assistant</blurb>=0A+<break/>=0A+<example inline=3D"2">=0A+= alias: Temperature MQTT Trigger=0A+description: ""=0A+triggers:=0A+ - trig= ger: state=0A+ entity_id:=0A+ - sensor.living_room_temperature=0A+ = *- sensor.current_temperature*=0A+ - binary_sensor.nest_on=0A+con= ditions: []=0A+actions:=0A+ - action: mqtt.publish=0A+ metadata: {}=0A+= data:=0A+ evaluate_payload: false=0A+ qos: 0=0A+ retain:= false=0A+ topic: tempwise/{{trigger.to_state.object_id}}/state_change= =0A+ payload: "{{trigger.from_state.state}}|{{trigger.to_state.state}}= "=0A+mode: single=0A+</example>=0A+</slide>=0Adiff --git a/slides/iot/ha-ne= st-data.xml b/slides/iot/ha-nest-data.xml=0Anew file mode 100644=0Aindex 00= 000000..da8d10d6=0A--- /dev/null=0A+++ b/slides/iot/ha-nest-data.xml=0A@@ -= 0,0 +1 @@=0A+<slide background=3D"ha-nest-slope-0.jpeg"/>=0Adiff --git a/sl= ides/iot/ha-nest-heat-slope1.png b/slides/iot/ha-nest-heat-slope1.png=0Anew= file mode 100644=0Aindex 00000000..27cc3d1f=0ABinary files /dev/null and b= /slides/iot/ha-nest-heat-slope1.png differ=0Adiff --git a/slides/iot/ha-nes= t-heat-slope2.png b/slides/iot/ha-nest-heat-slope2.png=0Anew file mode 1006= 44=0Aindex 00000000..383939c0=0ABinary files /dev/null and b/slides/iot/ha-= nest-heat-slope2.png differ=0Adiff --git a/slides/iot/ha-nest-schedule-alon= e.png b/slides/iot/ha-nest-schedule-alone.png=0Anew file mode 100644=0Ainde= x 00000000..0063f8ae=0ABinary files /dev/null and b/slides/iot/ha-nest-sche= dule-alone.png differ=0Adiff --git a/slides/iot/ha-nest-schedule.png b/slid= es/iot/ha-nest-schedule.png=0Anew file mode 100644=0Aindex 00000000..388d7a= 06=0ABinary files /dev/null and b/slides/iot/ha-nest-schedule.png differ=0A= diff --git a/slides/iot/ha-nest-schedule.xml b/slides/iot/ha-nest-schedule.= xml=0Anew file mode 100644=0Aindex 00000000..91f7afce=0A--- /dev/null=0A+++= b/slides/iot/ha-nest-schedule.xml=0A@@ -0,0 +1,23 @@=0A+<slide background= =3D"ha-nest-schedule.png">=0A+=0A+<div class=3D"left-side">=0A+<break lines= =3D"14"/>=0A+<div class=3D"light-bg">=0A+<div effect=3D"fade-in">=0A+<list>= <bullet>Schedules *Target* Temperature</bullet></list>=0A+</div>=0A+<div ef= fect=3D"fade-in">=0A+<list><bullet>Estimate Heating Efficiency</bullet></li= st>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>Is Inside/Outsid= e Temperature Differencial Important?</bullet></list>=0A+</div>=0A+<div eff= ect=3D"fade-in">=0A+<break lines=3D"3"/>=0A+<blurb>Future:</blurb>=0A+<list= ><bullet>Estimate Temperature Loss</bullet></list>=0A+</div>=0A+</div>=0A+<= /div>=0A+=0A+</slide>=0Adiff --git a/slides/iot/ha-nest-slope-0.jpeg b/slid= es/iot/ha-nest-slope-0.jpeg=0Anew file mode 100644=0Aindex 00000000..0cf95f= 58=0ABinary files /dev/null and b/slides/iot/ha-nest-slope-0.jpeg differ=0A= diff --git a/slides/iot/ha-nest-slope-1.jpeg b/slides/iot/ha-nest-slope-1.j= peg=0Anew file mode 100644=0Aindex 00000000..3749c7dd=0ABinary files /dev/n= ull and b/slides/iot/ha-nest-slope-1.jpeg differ=0Adiff --git a/slides/iot/= ha-nest-slope-2.jpeg b/slides/iot/ha-nest-slope-2.jpeg=0Anew file mode 1006= 44=0Aindex 00000000..2c9b4f6e=0ABinary files /dev/null and b/slides/iot/ha-= nest-slope-2.jpeg differ=0Adiff --git a/slides/iot/ha-nest-slope.xcf b/slid= es/iot/ha-nest-slope.xcf=0Anew file mode 100644=0Aindex 00000000..6904554e= =0ABinary files /dev/null and b/slides/iot/ha-nest-slope.xcf differ=0Adiff = --git a/slides/iot/ha-nest-slope1.png b/slides/iot/ha-nest-slope1.png=0Anew= file mode 100644=0Aindex 00000000..f1524b81=0ABinary files /dev/null and b= /slides/iot/ha-nest-slope1.png differ=0Adiff --git a/slides/iot/ha-nest-slo= pe2.png b/slides/iot/ha-nest-slope2.png=0Anew file mode 100644=0Aindex 0000= 0000..aee5c677=0ABinary files /dev/null and b/slides/iot/ha-nest-slope2.png= differ=0Adiff --git a/slides/iot/ha-nest-temperature.png b/slides/iot/ha-n= est-temperature.png=0Anew file mode 100644=0Aindex 00000000..deb9ddfa=0ABin= ary files /dev/null and b/slides/iot/ha-nest-temperature.png differ=0Adiff = --git a/slides/iot/ha-php-mqtt-code-rgb.xml b/slides/iot/ha-php-mqtt-code-r= gb.xml=0Anew file mode 100644=0Aindex 00000000..018460f8=0A--- /dev/null=0A= +++ b/slides/iot/ha-php-mqtt-code-rgb.xml=0A@@ -0,0 +1,58 @@=0A+<slide>=0A+= <title>Image Upgrade</title>=0A+=0A+<div effect=3D"fade-out">=0A+<blurb>Ima= ge Definition as RGB:</blurb>=0A+<example><![CDATA[=0A+$spritesRGB =3D [=0A= + 'sunny' =3D> [=0A+ 0, 0, 0, 5, 3, 1, 117, 97, 42, 140, 115, 47,= 140, 115, 47, 117, 98, 42, 0, 0,=0A+ 0, 0, 0, 0, 5, 3, 1, 81, 81, 0= , 245, 201, 77, 237, 193, 66, 237, 193, 66,=0A+ 245, 201, 77, 81, 81= , 0, 5, 4, 1, 116, 97, 41, 246, 202, 77, 251, 193, 58,=0A+ 253, 173,= 30, 250, 169, 26, 249, 190, 55, 245, 201, 77, 115, 96, 41, 140,=0A+ = 116, 47, 237, 193, 66, 252, 172, 30, 250, 168, 23, 248, 164, 17, 246, 162,= =0A+ 15, 237, 192, 66, 140, 116, 47, 139, 115, 47, 237, 193, 66, 250= , 168, 24,=0A+ 247, 164, 16, 245, 160, 11, 243, 158, 10, 237, 193, 6= 6, 141, 116, 48, 116,=0A+ 97, 42, 245, 201, 77, 248, 189, 54, 245, 1= 61, 14, 242, 158, 9, 246, 186,=0A+ 53, 244, 200, 77, 117, 98, 42, 5,= 3, 1, 81, 81, 0, 246, 202, 77, 237, 193,=0A+ 66, 236, 192, 66, 245,= 201, 77, 81, 81, 0, 0, 0, 0, 0, 0, 0, 5, 4, 1, 117,=0A+ 97, 42, 140= , 116, 47, 140, 115, 47, 115, 95, 41, 5, 4, 1, 0, 0, 0,=0A+ ],=0A+];]]><= /example>=0A+=0A+<blurb>Update MQTT Client Buffer Size:</blurb>=0A+<example= >=0A+- MQTTClient mqtt =3D MQTTClient();=0A++ MQTTClient mqtt =3D MQTTClien= t(1024);=0A+</example>=0A+</div>=0A+=0A+<div effect=3D"fade-in">=0A+<exampl= e>=0A+ if (strcmp("setlsrgb", command) =3D=3D 0) {=0A+ long start= =3D doc["s"], current =3D start, counter =3D 0;=0A+ unsigned char r= =3D 0, g =3D 0, b =3D 0;=0A+=0A+ JsonArray data =3D doc["d"];=0A+= =0A+ for (JsonVariant item : data) {=0A+ unsigned char va= lue =3D item;=0A+=0A+ if (counter % 3 =3D=3D 0) {=0A+ = r =3D value;=0A+ } else if (counter % 3 =3D=3D 1) {=0A+ = g =3D value;=0A+ } else {=0A+ b =3D v= alue;=0A+ devices[dev].setPixelColor(current % devices[dev].= numPixels(), r, g, b);=0A+ current++;=0A+ }=0A+= =0A+ counter++;=0A+ }=0A+ devices[dev].show();=0A+= }=0A+</example>=0A+</div>=0A+=0A+</slide>=0Adiff --git a/slides/iot/ha-= php-mqtt-code.xml b/slides/iot/ha-php-mqtt-code.xml=0Anew file mode 100644= =0Aindex 00000000..c95d9e87=0A--- /dev/null=0A+++ b/slides/iot/ha-php-mqtt-= code.xml=0A@@ -0,0 +1,82 @@=0A+<slide>=0A+<title>The PHP Code</title>=0A+= =0A+<div effect=3D"fade-out">=0A+<blurb>Connect to MQTT Broker:</blurb>=0A+= <example><![CDATA[=0A+<?php=0A+require 'vendor/autoload.php';=0A+=0A+$serve= r =3D '192.168.42.213';=0A+$port =3D 1883;=0A+$clientId =3D 'mqttfun-= esp32-react-on-weather';=0A+=0A+$connectionSettings =3D (new \PhpMqtt\Clien= t\ConnectionSettings)=0A+ ->setUsername("mqtt")=0A+ ->setPassword("ho= meassistant-XXXXXXXXXXXX");=0A+=0A+$mqtt =3D new \PhpMqtt\Client\MqttClient= ($server, $port, $clientId);=0A+$mqtt->connect($connectionSettings);=0A+]]>= </example>=0A+</div>=0A+<div effect=3D"fade-in-out">=0A+<blurb>Publish Simp= le Message:</blurb>=0A+<example><![CDATA[=0A+$docBrightness =3D [=0A+ 'c= ' =3D> 'setbrightness',=0A+ 'b' =3D> 20,=0A+];=0A+$mqtt->publish('esp32_= lights/1', json_encode($docBrightness), 0);=0A+]]></example>=0A+</div>=0A+<= div effect=3D"fade-in-out">=0A+<blurb>Subscribe Handler:</blurb>=0A+<exampl= e><![CDATA[=0A+$mqtt->subscribe('homeautomation/forecast',=0A+ function = ($topic, $message, $retained, $matchedWildcards) use ($sprites, $mqtt) {=0A= + $imageData =3D match ($message) {=0A+ 'rainy' =3D> $spr= ites['rainy'],=0A+ 'sunny' =3D> $sprites['sunny'],=0A+ = default =3D> $sprites['unknown'],=0A+ };=0A+=0A+ $mqttMessa= ge =3D [=0A+ 'c' =3D> 'setls',=0A+ 's' =3D> 0,=0A+ = 'd' =3D> $imageData,=0A+ ];=0A+ $mqtt->publish('esp3= 2_lights/1', json_encode($mqttMessage), 0);=0A+ },=0A+ 0=0A+);=0A+]]>= </example>=0A+</div>=0A+<div effect=3D"fade-in-out">=0A+<blurb>Loop:</blurb= >=0A+<example><![CDATA[=0A+$mqtt->loop(true);=0A+$mqtt->disconnect();=0A+]]= ></example>=0A+</div>=0A+=0A+<div effect=3D"fade-in">=0A+<blurb>Image Defin= ition(s):</blurb>=0A+<example><![CDATA[=0A+$sprites =3D [=0A+ =E2=80= =A6,=0A+ 'rainy' =3D> [=0A+ 0, 17, 0, 23, 20, 0, 0, 0,=0A= + 0, 18, 24, 25, 25, 25, 8, 18,=0A+ 19, 25, 25, 25, 25= , 24, 25, 23,=0A+ 24, 25, 25, 25, 24, 24, 24, 24,=0A+ 8,= 24, 24, 24, 24, 24, 24, 22,=0A+ 0, 55, 0, 18, 9, 55, 0, = 0,=0A+ 0, 0, 55, 176, 0, 104, 55, 0,=0A+ 0, 0, 127, 5= 5, 0, 0, 0, 55=0A+ ],=0A+ =E2=80=A6=0A+];]]></example>=0A+<image = filename=3D"icons.png"/>=0A+</div>=0A+=0A+</slide>=0Adiff --git a/slides/io= t/ha-php-mqtt-lego-box-design.xml b/slides/iot/ha-php-mqtt-lego-box-design.= xml=0Anew file mode 100644=0Aindex 00000000..c9992c61=0A--- /dev/null=0A+++= b/slides/iot/ha-php-mqtt-lego-box-design.xml=0A@@ -0,0 +1,3 @@=0A+<slide s= tyle=3D"title" background=3D"esp32-lego-box.png">=0A+<title>LEGO=E2=84= =A2 to the Rescue!</title>=0A+</slide>=0Adiff --git a/slides/iot/ha-php-mqt= t-lego-box-prototype.xml b/slides/iot/ha-php-mqtt-lego-box-prototype.xml=0A= new file mode 100644=0Aindex 00000000..3c1f4231=0A--- /dev/null=0A+++ b/sli= des/iot/ha-php-mqtt-lego-box-prototype.xml=0A@@ -0,0 +1,3 @@=0A+<slide styl= e=3D"title" background=3D"iot-weather-lego-prototype.jpeg">=0A+<title>It's = Still A Prototype=E2=80=A6</title>=0A+</slide>=0Adiff --git a/slides/iot/ha= -php-mqtt-next-animations.xml b/slides/iot/ha-php-mqtt-next-animations.xml= =0Anew file mode 100644=0Aindex 00000000..5a2e7133=0A--- /dev/null=0A+++ b/= slides/iot/ha-php-mqtt-next-animations.xml=0A@@ -0,0 +1,3 @@=0A+<slide styl= e=3D"title" background=3D"iot-weather-sunny.jpeg">=0A+<title>Future Plan: A= nimations</title>=0A+</slide>=0Adiff --git a/slides/iot/ha-php-mqtt-result-= rainy.xml b/slides/iot/ha-php-mqtt-result-rainy.xml=0Anew file mode 100644= =0Aindex 00000000..41a2c2e0=0A--- /dev/null=0A+++ b/slides/iot/ha-php-mqtt-= result-rainy.xml=0A@@ -0,0 +1 @@=0A+<slide background=3D"iot-weather-rainy.= jpeg"/>=0Adiff --git a/slides/iot/ha-php-mqtt-result-sunny.xml b/slides/iot= /ha-php-mqtt-result-sunny.xml=0Anew file mode 100644=0Aindex 00000000..6254= 4ac6=0A--- /dev/null=0A+++ b/slides/iot/ha-php-mqtt-result-sunny.xml=0A@@ -= 0,0 +1 @@=0A+<slide background=3D"iot-weather-sunny.jpeg"/>=0Adiff --git a/= slides/iot/ha-php-mqtt-result-unknown.xml b/slides/iot/ha-php-mqtt-result-u= nknown.xml=0Anew file mode 100644=0Aindex 00000000..9fd7d8b8=0A--- /dev/nul= l=0A+++ b/slides/iot/ha-php-mqtt-result-unknown.xml=0A@@ -0,0 +1 @@=0A+<sli= de background=3D"iot-weather-unknown.jpeg"/>=0Adiff --git a/slides/iot/ha-p= hp-mqtt-result.xml b/slides/iot/ha-php-mqtt-result.xml=0Anew file mode 1006= 44=0Aindex 00000000..41a2c2e0=0A--- /dev/null=0A+++ b/slides/iot/ha-php-mqt= t-result.xml=0A@@ -0,0 +1 @@=0A+<slide background=3D"iot-weather-rainy.jpeg= "/>=0Adiff --git a/slides/iot/ha-php-mqtt.xml b/slides/iot/ha-php-mqtt.xml= =0Anew file mode 100644=0Aindex 00000000..a09a23d8=0A--- /dev/null=0A+++ b/= slides/iot/ha-php-mqtt.xml=0A@@ -0,0 +1,28 @@=0A+<slide>=0A+<title>Step 4: = Glue Between HA Forecast and ESP32</title>=0A+=0A+<div class=3D"light-bg">= =0A+<div effect=3D"fade-in">=0A+<list><bullet>Subscribe to MQTT Topic %home= automation/forecast%</bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">= =0A+<list><bullet>Figure Out Which Image to Use</bullet></list>=0A+</div>= =0A+<div effect=3D"fade-in">=0A+<list><bullet>Publish Complex Message to %e= sp32_lights/1%</bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<br= eak lines=3D"2"/>=0A+<list><bullet>PHP is a great language for this</bullet= ></list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>MQTT Client= on Packagist: %php-mqtt/client%</bullet></list>=0A+</div>=0A+</div>=0A+=0A= +<div effect=3D"fade-in">=0A+<break lines=3D"3"/>=0A+<image filename=3D"ico= ns.png"/>=0A+</div>=0A+=0A+</slide>=0Adiff --git a/slides/iot/ha-program-es= p32-board.xml b/slides/iot/ha-program-esp32-board.xml=0Anew file mode 10064= 4=0Aindex 00000000..eade86bf=0A--- /dev/null=0A+++ b/slides/iot/ha-program-= esp32-board.xml=0A@@ -0,0 +1,36 @@=0A+<slide background=3D"esp32-code.png">= =0A+<title>Step 2: Program a Micro Controller to Drive the LED Matrix</titl= e>=0A+=0A+<div class=3D"left-side">=0A+<div class=3D"light-bg">=0A+<div eff= ect=3D"fade-in">=0A+<list><bullet>Arduino IDE =E2=86=92 CLI</bullet></list>= =0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>C / C++</bullet></l= ist>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>Connecting to W= iFi</bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>= Connecting to MQTT and Handling Messages</bullet></list>=0A+</div>=0A+<div = effect=3D"fade-in">=0A+<list><bullet>Use Messages to Write Images</bullet><= /list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>Re-learn Abou= t Palettes</bullet></list>=0A+</div>=0A+</div>=0A+</div>=0A+=0A+<div class= =3D"right-side">=0A+<break lines=3D"12"/>=0A+<div class=3D"light-bg">=0A+<d= iv effect=3D"fade-in">=0A+<image filename=3D"esp32-vga-palette.png"/>=0A+</= div>=0A+</div>=0A+</div>=0A+=0A+</slide>=0Adiff --git a/slides/iot/ha-senso= r-current-temp1.png b/slides/iot/ha-sensor-current-temp1.png=0Anew file mod= e 100644=0Aindex 00000000..b1b14e24=0ABinary files /dev/null and b/slides/i= ot/ha-sensor-current-temp1.png differ=0Adiff --git a/slides/iot/ha-sensor-c= urrent-temp2.png b/slides/iot/ha-sensor-current-temp2.png=0Anew file mode 1= 00644=0Aindex 00000000..3e8d5ed0=0ABinary files /dev/null and b/slides/iot/= ha-sensor-current-temp2.png differ=0Adiff --git a/slides/iot/ha-smooth-brig= htness.png b/slides/iot/ha-smooth-brightness.png=0Anew file mode 100644=0Ai= ndex 00000000..351a0673=0ABinary files /dev/null and b/slides/iot/ha-smooth= -brightness.png differ=0Adiff --git a/slides/iot/ha-tree-lights.png b/slide= s/iot/ha-tree-lights.png=0Anew file mode 100644=0Aindex 00000000..16572c30= =0ABinary files /dev/null and b/slides/iot/ha-tree-lights.png differ=0Adiff= --git a/slides/iot/ha-zigbee-network.png b/slides/iot/ha-zigbee-network.pn= g=0Anew file mode 100644=0Aindex 00000000..52e9d7bf=0ABinary files /dev/nul= l and b/slides/iot/ha-zigbee-network.png differ=0Adiff --git a/slides/iot/h= eating-rate.png b/slides/iot/heating-rate.png=0Anew file mode 100644=0Ainde= x 00000000..5c9dc77f=0ABinary files /dev/null and b/slides/iot/heating-rate= .png differ=0Adiff --git a/slides/iot/heating-schedule.png b/slides/iot/hea= ting-schedule.png=0Anew file mode 100644=0Aindex 00000000..5c29702d=0ABinar= y files /dev/null and b/slides/iot/heating-schedule.png differ=0Adiff --git= a/slides/iot/home-assistant-1.xml b/slides/iot/home-assistant-1.xml=0Anew = file mode 100644=0Aindex 00000000..a259816b=0A--- /dev/null=0A+++ b/slides/= iot/home-assistant-1.xml=0A@@ -0,0 +1,19 @@=0A+<slide background=3D"iot-hom= eassistant.jpeg">=0A+<title>Home Assistant</title>=0A+=0A+<div effect=3D"fa= de-in">=0A+<break lines=3D"1"/>=0A+<div class=3D"light-bg right-side">=0A+<= image filename=3D"iot-homeassistant-zigbee.jpeg"/>=0A+<blurb align=3D"cente= r">Home Assistant Zigbee Dongle</blurb>=0A+</div>=0A+</div>=0A+=0A+<div eff= ect=3D"fade-in">=0A+<break lines=3D"15"/>=0A+<div class=3D"light-bg left-si= de">=0A+<image filename=3D"the_internet_from_the_it_crowd.jpeg"/>=0A+<blurb= align=3D"center">"The Internet"</blurb>=0A+</div>=0A+</div>=0A+</slide>=0A= diff --git a/slides/iot/icons.png b/slides/iot/icons.png=0Anew file mode 10= 0644=0Aindex 00000000..0badaaf5=0ABinary files /dev/null and b/slides/iot/i= cons.png differ=0Adiff --git a/slides/iot/iot-elephpant-shelf.jpeg b/slides= /iot/iot-elephpant-shelf.jpeg=0Anew file mode 100644=0Aindex 00000000..1992= 0712=0ABinary files /dev/null and b/slides/iot/iot-elephpant-shelf.jpeg dif= fer=0Adiff --git a/slides/iot/iot-esp32-matrix.jpeg b/slides/iot/iot-esp32-= matrix.jpeg=0Anew file mode 100644=0Aindex 00000000..7e8a3453=0ABinary file= s /dev/null and b/slides/iot/iot-esp32-matrix.jpeg differ=0Adiff --git a/sl= ides/iot/iot-homeassistant-zigbee.jpeg b/slides/iot/iot-homeassistant-zigbe= e.jpeg=0Anew file mode 100644=0Aindex 00000000..8ddf127e=0ABinary files /de= v/null and b/slides/iot/iot-homeassistant-zigbee.jpeg differ=0Adiff --git a= /slides/iot/iot-homeassistant.jpeg b/slides/iot/iot-homeassistant.jpeg=0Ane= w file mode 100644=0Aindex 00000000..e92ea76e=0ABinary files /dev/null and = b/slides/iot/iot-homeassistant.jpeg differ=0Adiff --git a/slides/iot/iot-hu= man-detector.jpeg b/slides/iot/iot-human-detector.jpeg=0Anew file mode 1006= 44=0Aindex 00000000..866e14c5=0ABinary files /dev/null and b/slides/iot/iot= -human-detector.jpeg differ=0Adiff --git a/slides/iot/iot-lamp-dim.gif b/sl= ides/iot/iot-lamp-dim.gif=0Anew file mode 100644=0Aindex 00000000..c89ed8b6= =0ABinary files /dev/null and b/slides/iot/iot-lamp-dim.gif differ=0Adiff -= -git a/slides/iot/iot-lego-lights.jpeg b/slides/iot/iot-lego-lights.jpeg=0A= new file mode 100644=0Aindex 00000000..c657ae98=0ABinary files /dev/null an= d b/slides/iot/iot-lego-lights.jpeg differ=0Adiff --git a/slides/iot/iot-ma= trix-sun-paper.jpeg b/slides/iot/iot-matrix-sun-paper.jpeg=0Anew file mode = 100644=0Aindex 00000000..fbecb9d3=0ABinary files /dev/null and b/slides/iot= /iot-matrix-sun-paper.jpeg differ=0Adiff --git a/slides/iot/iot-monty.jpeg = b/slides/iot/iot-monty.jpeg=0Anew file mode 100644=0Aindex 00000000..850044= 02=0ABinary files /dev/null and b/slides/iot/iot-monty.jpeg differ=0Adiff -= -git a/slides/iot/iot-motion-detector.jpeg b/slides/iot/iot-motion-detector= .jpeg=0Anew file mode 100644=0Aindex 00000000..ac02dd69=0ABinary files /dev= /null and b/slides/iot/iot-motion-detector.jpeg differ=0Adiff --git a/slide= s/iot/iot-smartlife-plug.jpeg b/slides/iot/iot-smartlife-plug.jpeg=0Anew fi= le mode 100644=0Aindex 00000000..7528a595=0ABinary files /dev/null and b/sl= ides/iot/iot-smartlife-plug.jpeg differ=0Adiff --git a/slides/iot/iot-strea= mdeck-home.jpeg b/slides/iot/iot-streamdeck-home.jpeg=0Anew file mode 10064= 4=0Aindex 00000000..06b9d440=0ABinary files /dev/null and b/slides/iot/iot-= streamdeck-home.jpeg differ=0Adiff --git a/slides/iot/iot-streamdeck-obs.jp= eg b/slides/iot/iot-streamdeck-obs.jpeg=0Anew file mode 100644=0Aindex 0000= 0000..9fb6d260=0ABinary files /dev/null and b/slides/iot/iot-streamdeck-obs= .jpeg differ=0Adiff --git a/slides/iot/iot-weather-lego-prototype.jpeg b/sl= ides/iot/iot-weather-lego-prototype.jpeg=0Anew file mode 100644=0Aindex 000= 00000..140ff761=0ABinary files /dev/null and b/slides/iot/iot-weather-lego-= prototype.jpeg differ=0Adiff --git a/slides/iot/iot-weather-lego-prototype.= jpeg.jpeg b/slides/iot/iot-weather-lego-prototype.jpeg.jpeg=0Anew file mode= 100644=0Aindex 00000000..140ff761=0ABinary files /dev/null and b/slides/io= t/iot-weather-lego-prototype.jpeg.jpeg differ=0Adiff --git a/slides/iot/iot= -weather-rainy.jpeg b/slides/iot/iot-weather-rainy.jpeg=0Anew file mode 100= 644=0Aindex 00000000..39564050=0ABinary files /dev/null and b/slides/iot/io= t-weather-rainy.jpeg differ=0Adiff --git a/slides/iot/iot-weather-sunny.jpe= g b/slides/iot/iot-weather-sunny.jpeg=0Anew file mode 100644=0Aindex 000000= 00..4995591d=0ABinary files /dev/null and b/slides/iot/iot-weather-sunny.jp= eg differ=0Adiff --git a/slides/iot/iot-weather-unknown.jpeg b/slides/iot/i= ot-weather-unknown.jpeg=0Anew file mode 100644=0Aindex 00000000..25fa1589= =0ABinary files /dev/null and b/slides/iot/iot-weather-unknown.jpeg differ= =0Adiff --git a/slides/iot/iot-wedding-tree-switch.jpeg b/slides/iot/iot-we= dding-tree-switch.jpeg=0Anew file mode 100644=0Aindex 00000000..a03759b2=0A= Binary files /dev/null and b/slides/iot/iot-wedding-tree-switch.jpeg differ= =0Adiff --git a/slides/iot/iot-wedding-tree.jpeg b/slides/iot/iot-wedding-t= ree.jpeg=0Anew file mode 100644=0Aindex 00000000..e2d6e22b=0ABinary files /= dev/null and b/slides/iot/iot-wedding-tree.jpeg differ=0Adiff --git a/slide= s/iot/lights-options.png b/slides/iot/lights-options.png=0Anew file mode 10= 0644=0Aindex 00000000..3077dca8=0ABinary files /dev/null and b/slides/iot/l= ights-options.png differ=0Adiff --git a/slides/iot/livingroom-ok.xml b/slid= es/iot/livingroom-ok.xml=0Anew file mode 100644=0Aindex 00000000..5291b7a0= =0A--- /dev/null=0A+++ b/slides/iot/livingroom-ok.xml=0A@@ -0,0 +1,19 @@=0A= +<slide>=0A+<title>What Are We Using It For?</title>=0A+=0A+<image filename= =3D"lights-options.png"/>=0A+=0A+=0A+<div class=3D"light-bg right-side">=0A= +<break/>=0A+<image filename=3D"heating-schedule.png"/>=0A+<blurb class=3D"= small center">Heating Schedule</blurb>=0A+</div>=0A+=0A+<break lines=3D"2"/= >=0A+<blurb>Things to do:</blurb>=0A+<list>=0A+=09<bullet>Automation for tu= rning the heating to Eco mode</bullet>=0A+=09<bullet>Cleverder Heating</bul= let>=0A+</list>=0A+</slide>=0Adiff --git a/slides/iot/livingroom-party.xml = b/slides/iot/livingroom-party.xml=0Anew file mode 100644=0Aindex 00000000..= b56ccdb8=0A--- /dev/null=0A+++ b/slides/iot/livingroom-party.xml=0A@@ -0,0 = +1,6 @@=0A+<slide style=3D"title" background=3D"party-lights.gif">=0A+<titl= e>Party Lights</title>=0A+=0A+<div effect=3D"fade-in"><break lines=3D"26"/>= <blurb class=3D"big-centre">*NOT ALLOWED*</blurb></div>=0A+=0A+</slide>=0Ad= iff --git a/slides/iot/monty.xml b/slides/iot/monty.xml=0Anew file mode 100= 644=0Aindex 00000000..827d9bec=0A--- /dev/null=0A+++ b/slides/iot/monty.xml= =0A@@ -0,0 +1,4 @@=0A+<slide style=3D"title" background=3D"iot-monty.jpeg">= =0A+<title>Monty</title>=0A+</slide>=0A+=0Adiff --git a/slides/iot/mqtt-int= egration.png b/slides/iot/mqtt-integration.png=0Anew file mode 100644=0Aind= ex 00000000..bd890427=0ABinary files /dev/null and b/slides/iot/mqtt-integr= ation.png differ=0Adiff --git a/slides/iot/mqtt-logo.svg b/slides/iot/mqtt-= logo.svg=0Anew file mode 100644=0Aindex 00000000..b0df6127=0A--- /dev/null= =0A+++ b/slides/iot/mqtt-logo.svg=0A@@ -0,0 +1,23 @@=0A+<?xml version=3D"1.= 0" encoding=3D"UTF-8"?>=0A+<!-- Generator: Adobe Illustrator 24.2.1, SVG Ex= port Plug-In . SVG Version: 6.00 Build 0) -->=0A+<svg version=3D"1.2" base= Profile=3D"tiny" xmlns=3D"http://www.w3.org/2000/svg" xmlns:xlink=3D"http:/= /www.w3.org/1999/xlink" x=3D"0px" y=3D"0px" viewBox=3D"0 0 1100 320" overfl= ow=3D"visible" xml:space=3D"preserve">=0A+<g id=3D"black_bg" display=3D"non= e">=0A+</g>=0A+<g id=3D"logos">=0A+=09<g>=0A+=09=09<g>=0A+=09=09=09<path fi= ll=3D"#660066" d=3D"M399.6,165.3c1.7,3.7,3.3,7.5,4.8,11.4c1.5-4,3.1-7.8,4.9= -11.6c1.7-3.7,3.5-7.4,5.3-10.9L465,54.8 c0.9-1.7,1.8-3,2.8-4c0.9-0.9,2-= 1.6,3.2-2.1c1.2-0.5,2.5-0.7,4-0.7c1.5,0,3.2,0,5.2,0H515v196.6h-40.2V131.4 = c0-5.5,0.3-11.4,0.8-17.8l-52.1,101.1c-1.6,3.2-3.8,5.5-6.5,7.2c-2.7,1.6-5= .9,2.4-9.4,2.4h-6.2c-3.5,0-6.6-0.8-9.4-2.4 c-2.7-1.6-4.9-4-6.5-7.2L333,= 113.5c0.4,3.2,0.6,6.3,0.8,9.4c0.2,3.1,0.3,6,0.3,8.6v113.1h-40.2V48h34.8c2,0= ,3.7,0,5.2,0 s2.8,0.2,4,0.7c1.2,0.5,2.2,1.1,3.2,2.1c0.9,0.9,1.9,2.3,2.8= ,4l50.6,99.9C396.2,158.1,398,161.6,399.6,165.3z"/>=0A+=09=09=09<path fill= =3D"#660066" d=3D"M730.7,146.2c0,8.5-0.9,16.6-2.6,24.4c-1.8,7.8-4.3,15.1-7.= 6,21.9c-3.3,6.8-7.3,13.2-12.2,19 c-4.8,5.9-10.3,11-16.4,15.5l49.8,54.4h= -37.5c-5.4,0-10.3-0.7-14.7-2c-4.4-1.3-8.3-3.9-11.7-7.9l-24.4-27.4 c-4,0= .8-8,1.4-12.1,1.9c-4.1,0.4-8.3,0.7-12.6,0.7c-15.3,0-29.3-2.6-41.9-7.7c-12.6= -5.1-23.4-12.2-32.3-21.3 c-9-9-15.9-19.7-20.8-31.9c-4.9-12.2-7.4-25.5-7= .4-39.7c0-14.2,2.5-27.4,7.4-39.7c4.9-12.2,11.8-22.9,20.8-31.9 c9-9,19.7= -16.1,32.3-21.2c12.6-5.1,26.5-7.7,41.9-7.7c15.3,0,29.2,2.6,41.8,7.8c12.6,5.= 2,23.3,12.3,32.2,21.3 c8.9,9,15.8,19.6,20.7,31.9C728.3,118.8,730.7,132,= 730.7,146.2z M684,146.2c0-9.7-1.3-18.5-3.8-26.3c-2.5-7.8-6.1-14.4-10.9-19.8= c-4.7-5.4-10.5-9.5-17.3-12.4c-6.8-2.9-14.6-4.3-23.4-4.3c-8.8,0-16.7,1.= 4-23.6,4.3c-6.9,2.9-12.7,7-17.4,12.4 c-4.7,5.4-8.3,12-10.9,19.8c-2.5,7.= 8-3.8,16.5-3.8,26.3c0,9.8,1.3,18.6,3.8,26.4c2.5,7.8,6.1,14.4,10.9,19.8 = c4.7,5.4,10.5,9.5,17.4,12.4c6.9,2.8,14.7,4.3,23.6,4.3c8.7,0,16.5-1.4,23.4-4= .3c6.8-2.8,12.6-7,17.3-12.4 c4.7-5.4,8.3-12,10.9-19.8C682.8,164.8,684,1= 56,684,146.2z"/>=0A+=09=09=09<path fill=3D"#660066" d=3D"M877.2,47.9v36.2h-= 53.3v160.5h-45.6V84.1h-53.3V47.9H877.2z"/>=0A+=09=09=09<path fill=3D"#66006= 6" d=3D"M1051.8,47.9v36.2h-55.3v160.5h-45.6V84.1h-53.3V47.9H1051.8z"/>=0A+= =09=09</g>=0A+=09</g>=0A+=09<path fill=3D"#FFFFFF" d=3D"M46,64.2v31c0.2,0,0= .4,0,0.6,0c84.4,0,153.2,68,153.9,151.8h30.1C229.8,146.3,147.4,64.5,46,64.2z= "/>=0A+=09<path fill=3D"#FFFFFF" d=3D"M46,128.2v31c0.2,0,0.4,0,0.6,0c48.9,0= ,88.8,39.3,89.5,87.8h30.1C165.5,181.6,111.9,128.5,46,128.2z"/>=0A+=09<path = fill=3D"#FFFFFF" d=3D"M248.8,166.8v-62.5c-7.7-10.5-17.2-22.5-26.7-31.8c-10.= 6-10.5-23-20-35-28.3h-66.4 C178.9,65.1,225.6,110,248.8,166.8z"/>=0A+=09<p= ath fill=3D"#660066" d=3D"M46.5,159.2c-0.2,0-0.4,0-0.6,0v77.6c0,5.6,4.6,10.= 2,10.2,10.2H136C135.3,198.5,95.5,159.2,46.5,159.2z"/>=0A+=09<path fill=3D"#= 660066" d=3D"M46.5,95.2c-0.2,0-0.4,0-0.6,0v33c65.9,0.3,119.5,53.3,120.2,118= .8h34.2C199.7,163.2,131,95.2,46.5,95.2z"/>=0A+=09<path fill=3D"#660066" d= =3D"M248.8,236.9v-70.1c-23.2-56.8-69.9-101.7-128-122.6H56.1c-5.6,0-10.2,4.6= -10.2,10.2v9.9 c101.4,0.3,183.9,82,184.5,182.8h8.2C244.3,247,248.8,242.5,= 248.8,236.9z"/>=0A+=09<path fill=3D"#660066" d=3D"M222.1,72.5c9.4,9.4,19,21= .3,26.7,31.8v-50c0-5.6-4.5-10.1-10.1-10.1h-51.5C199.2,52.5,211.6,62,222.1,7= 2.5 z"/>=0A+</g>=0A+</svg>=0A\ No newline at end of file=0Adiff --git a/s= lides/iot/mqtt-project-goal.xml b/slides/iot/mqtt-project-goal.xml=0Anew fi= le mode 100644=0Aindex 00000000..69329fc2=0A--- /dev/null=0A+++ b/slides/io= t/mqtt-project-goal.xml=0A@@ -0,0 +1,19 @@=0A+<slide background=3D"iot-stre= amdeck-obs.jpeg">=0A+<title>Goal: Dim the Stream Deck When I Leave The Room= </title>=0A+=0A+<div effect=3D"fade-in">=0A+<break lines=3D"1"/>=0A+<div cl= ass=3D"light-bg left-side">=0A+<image filename=3D"iot-human-detector.jpeg" = width=3D"800"/>=0A+<blurb align=3D"center">Human Detector</blurb>=0A+</div>= =0A+</div>=0A+=0A+<div effect=3D"fade-in">=0A+<break lines=3D"8"/>=0A+<div = class=3D"light-bg right-side">=0A+<image filename=3D"iot-homeassistant.jpeg= " width=3D"800"/>=0A+<blurb align=3D"center">Home Assistant</blurb>=0A+</di= v>=0A+</div>=0A+</slide>=0Adiff --git a/slides/iot/mqtt-whats-next-elephpan= ts.xml b/slides/iot/mqtt-whats-next-elephpants.xml=0Anew file mode 100644= =0Aindex 00000000..c0326ad1=0A--- /dev/null=0A+++ b/slides/iot/mqtt-whats-n= ext-elephpants.xml=0A@@ -0,0 +1,3 @@=0A+<slide style=3D"title" background= =3D"iot-elephpant-shelf.jpeg">=0A+<title>Future Plan: Light Up The Elephpan= ts</title>=0A+</slide>=0Adiff --git a/slides/iot/mqtt-whats-next-esp32-boar= d.xml b/slides/iot/mqtt-whats-next-esp32-board.xml=0Anew file mode 100644= =0Aindex 00000000..184184aa=0A--- /dev/null=0A+++ b/slides/iot/mqtt-whats-n= ext-esp32-board.xml=0A@@ -0,0 +1,8 @@=0A+<slide background=3D"iot-esp32-mat= rix.jpeg">=0A+<title>Step 3: Learn How To Solder=E2=80=A6</title>=0A+=0A+<b= reak lines=3D"12"/>=0A+<div class=3D"light-bg right-side">=0A+<image filena= me=3D"esp32-schematic.png"/>=0A+</div>=0A+</slide>=0Adiff --git a/slides/io= t/mqtt-whats-next-lego.xml b/slides/iot/mqtt-whats-next-lego.xml=0Anew file= mode 100644=0Aindex 00000000..028db644=0A--- /dev/null=0A+++ b/slides/iot/= mqtt-whats-next-lego.xml=0A@@ -0,0 +1,3 @@=0A+<slide style=3D"title" backgr= ound=3D"iot-lego-lights.jpeg">=0A+<title>Future Plan: Be Clever With the Le= go Space Model Lights</title>=0A+</slide>=0Adiff --git a/slides/iot/mqtt-wh= ats-next-weather-matrix.xml b/slides/iot/mqtt-whats-next-weather-matrix.xml= =0Anew file mode 100644=0Aindex 00000000..c8417240=0A--- /dev/null=0A+++ b/= slides/iot/mqtt-whats-next-weather-matrix.xml=0A@@ -0,0 +1,3 @@=0A+<slide s= tyle=3D"title" background=3D"iot-matrix-sun-paper.jpeg">=0A+<title>Future P= lan: Push Weather Forecast to LED Matrix</title>=0A+</slide>=0Adiff --git a= /slides/iot/mqtt-whats-next.xml b/slides/iot/mqtt-whats-next.xml=0Anew file= mode 100644=0Aindex 00000000..9b770e71=0A--- /dev/null=0A+++ b/slides/iot/= mqtt-whats-next.xml=0A@@ -0,0 +1,28 @@=0A+<slide style=3D"title">=0A+<blurb= class=3D"large">Step 5: Publish to MQTT</blurb>=0A+<break/>=0A+<blurb>Conf= iguration:</blurb>=0A+<example inline=3D"2">=0A+HousePage:=0A+ - Index: 0= =0A+ Type: mqtt-color=0A+ Arguments:=0A+ - StateId: office-lights= =0A+ - Name: "LIGHT"=0A+ - PublishTopic: "homeautomation/office"=0A= + - ActivePublishPayload: "light"=0A+ - InactivePublishPayload: "da= rk"=0A+ - ActiveStateColor: "#00ff00"=0A+ - InactiveStateColor: "#f= f0000"=0A+</example>=0A+<break/>=0A+=0A+<blurb>To publish to MQTT:</blurb>= =0A+<example inline=3D"2">=0A+mq.mqtt.mqtt_client.Publish(mq.PublishTopic, = 0, false, mq.NextPublishPayload)=0A+</example>=0A+=0A+<break/>=0A+<blurb>Ho= oking it into the Streamdeck-Goui code was trickier=E2=80=A6</blurb>=0A+=0A= +</slide>=0Adiff --git a/slides/iot/mqtt.xml b/slides/iot/mqtt.xml=0Anew fi= le mode 100644=0Aindex 00000000..7a82515f=0A--- /dev/null=0A+++ b/slides/io= t/mqtt.xml=0A@@ -0,0 +1,14 @@=0A+<slide>=0A+=0A+<break lines=3D"4"/>=0A+<im= age filename=3D"mqtt-logo.svg"/>=0A+=0A+<break lines=3D"2"/>=0A+<blurb clas= s=3D"center">=0A+MQTT is a lightweight, publish=E2=80=93subscribe, machine-= to-machine network protocol=0A+for message queue/message queuing service. I= t is designed for connections with=0A+remote locations that have devices wi= th resource constraints or limited network=0A+bandwidth, such as in the Int= ernet of things (IoT).=0A+</blurb>=0A+=0A+</slide>=0Adiff --git a/slides/io= t/office-lights-dim.xml b/slides/iot/office-lights-dim.xml=0Anew file mode = 100644=0Aindex 00000000..0d9460c1=0A--- /dev/null=0A+++ b/slides/iot/office= -lights-dim.xml=0A@@ -0,0 +1,19 @@=0A+<slide>=0A+<title>Dimming Lights</tit= le>=0A+=0A+<div class=3D"light-bg right-side">=0A+<image filename=3D"ha-dim= -lights-action.png"/>=0A+</div>=0A+=0A+<blurb>*Ceiling Office Light*</blurb= >=0A+<list>=0A+<bullet>Brighten when you enter the room</bullet>=0A+<bullet= >Dim when you leave the room</bullet>=0A+</list>=0A+=0A+<break/>=0A+<div cl= ass=3D"light-bg left-side">=0A+<image filename=3D"iot-lamp-dim.gif"/>=0A+</= div>=0A+=0A+</slide>=0Adiff --git a/slides/iot/office-lights-goals.xml b/sl= ides/iot/office-lights-goals.xml=0Anew file mode 100644=0Aindex 00000000..6= d37eaaa=0A--- /dev/null=0A+++ b/slides/iot/office-lights-goals.xml=0A@@ -0,= 0 +1,24 @@=0A+<slide>=0A+<title>Office Lights: Goals</title>=0A+=0A+<blurb>= *Standing Office Light*</blurb>=0A+<list>=0A+<bullet>Turn off if you leave = for 5 minutes</bullet>=0A+<bullet>Turn off when it gets *bright enough*</bu= llet>=0A+<bullet>Turn on when a human enters the room and it's *darkish*</b= ullet>=0A+<bullet>Turn on when it turns *darkish* and there is a human ther= e</bullet>=0A+</list>=0A+=0A+<div effect=3D"fade-in">=0A+<break/>=0A+<blurb= >*Ceiling Office Light*</blurb>=0A+<list>=0A+<bullet>Brighten when you ente= r the room</bullet>=0A+<bullet>Dim when you leave the room</bullet>=0A+<bul= let>Turn off if nobody is in the room for more than 5 minutes</bullet>=0A+<= bullet>Turn off when it's *bright enough*</bullet>=0A+<bullet>Turn on when = its *darkish*</bullet>=0A+<bullet>Turn on when you enter the room and it is= *darkish*</bullet>=0A+</list>=0A+</div>=0A+</slide>=0Adiff --git a/slides/= iot/office-lights-turn-off-bright-enough.xml b/slides/iot/office-lights-tur= n-off-bright-enough.xml=0Anew file mode 100644=0Aindex 00000000..a25601d4= =0A--- /dev/null=0A+++ b/slides/iot/office-lights-turn-off-bright-enough.xm= l=0A@@ -0,0 +1,21 @@=0A+<slide>=0A+<title>Turn Off When It's Bright</title>= =0A+=0A+<div class=3D"light-bg right-side">=0A+<image filename=3D"iot-motio= n-detector.jpeg"/>=0A+<blurb align=3D"center" class=3D"small">Motion Detect= or</blurb>=0A+</div>=0A+=0A+<blurb>Standing Office Light</blurb>=0A+<list>= =0A+<bullet>Turn off when it gets *bright enough*</bullet>=0A+</list>=0A+= =0A+<blurb>Ceiling Office Light</blurb>=0A+<list>=0A+<bullet>Turn off when = it's *bright enough*</bullet>=0A+</list>=0A+=0A+<image filename=3D"ha-actio= n-turn-lights-off-bright.png"/>=0A+=0A+</slide>=0Adiff --git a/slides/iot/o= ffice-lights-turn-off-leave.xml b/slides/iot/office-lights-turn-off-leave.x= ml=0Anew file mode 100644=0Aindex 00000000..872ebe63=0A--- /dev/null=0A+++ = b/slides/iot/office-lights-turn-off-leave.xml=0A@@ -0,0 +1,21 @@=0A+<slide>= =0A+<title>Turn Off When Leaving</title>=0A+=0A+<div class=3D"light-bg righ= t-side">=0A+<image filename=3D"iot-human-detector.jpeg"/>=0A+<blurb align= =3D"center" class=3D"small">Human Presense Sensor</blurb>=0A+</div>=0A+=0A+= <blurb>Standing Office Light</blurb>=0A+<list>=0A+<bullet>Turn off if you l= eave for 5 minutes</bullet>=0A+</list>=0A+=0A+<blurb>Ceiling Office Light</= blurb>=0A+<list>=0A+<bullet>Turn off if nobody is in the room for more than= 5 minutes</bullet>=0A+</list>=0A+=0A+<image filename=3D"ha-action-turn-lig= hts-off.png"/>=0A+=0A+</slide>=0Adiff --git a/slides/iot/office-lights-turn= -on.xml b/slides/iot/office-lights-turn-on.xml=0Anew file mode 100644=0Aind= ex 00000000..0ff156c1=0A--- /dev/null=0A+++ b/slides/iot/office-lights-turn= -on.xml=0A@@ -0,0 +1,29 @@=0A+<slide>=0A+<title>Turn On When It's Dark</tit= le>=0A+=0A+<div class=3D"light-bg right-side">=0A+<image filename=3D"ha-act= ions-turn-lights-on.png"/>=0A+</div>=0A+=0A+<div class=3D"left-side">=0A+<b= lurb>Standing Office Light</blurb>=0A+<list>=0A+<bullet>Turn on when a huma= n enters the room and it's *darkish*</bullet>=0A+<bullet>Turn on when it tu= rns *darkish* and there is a human there</bullet>=0A+</list>=0A+=0A+<blurb>= Ceiling Office Light</blurb>=0A+<list>=0A+<bullet>Turn on when its *darkish= *</bullet>=0A+<bullet>Turn on when you enter the room and it is *darkish*</= bullet>=0A+</list>=0A+<break/>=0A+<blurb>Needs a filter helper to provide s= moothed value</blurb>=0A+</div>=0A+=0A+<div class=3D"light-bg right-side">= =0A+<image filename=3D"ha-smooth-brightness.png"/>=0A+</div>=0A+=0A+</slide= >=0A+=0Adiff --git a/slides/iot/party-lights.gif b/slides/iot/party-lights.= gif=0Anew file mode 100644=0Aindex 00000000..9a10b6e7=0ABinary files /dev/n= ull and b/slides/iot/party-lights.gif differ=0Adiff --git a/slides/iot/smar= t-plug-1.xml b/slides/iot/smart-plug-1.xml=0Anew file mode 100644=0Aindex 0= 0000000..991faf76=0A--- /dev/null=0A+++ b/slides/iot/smart-plug-1.xml=0A@@ = -0,0 +1,15 @@=0A+<slide background=3D"iot-smartlife-plug.jpeg">=0A+<title>S= martLife Plug</title>=0A+=0A+<div effect=3D"fade-in">=0A+<break lines=3D"21= "/>=0A+<div class=3D"light-bg left-side">=0A+<break lines=3D"1"/>=0A+<list>= =0A+=09<bullet>Requires an app</bullet>=0A+=09<bullet>Requires the internet= </bullet>=0A+</list>=0A+<break lines=3D"1"/>=0A+</div>=0A+</div>=0A+</slide= >=0Adiff --git a/slides/iot/streamdeck.xml b/slides/iot/streamdeck.xml=0Ane= w file mode 100644=0Aindex 00000000..99420b1a=0A--- /dev/null=0A+++ b/slide= s/iot/streamdeck.xml=0A@@ -0,0 +1,60 @@=0A+<slide background=3D"iot-streamd= eck-home.jpeg">=0A+=0A+<div class=3D"left-side">=0A+<break lines=3D"8"/>=0A= +<div class=3D"light-bg">=0A+<div effect=3D"fade-in">=0A+<list><bullet>Run = a Shell Command</bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<l= ist><bullet>A Clock</bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">= =0A+<list><bullet>Control My Streaming Light</bullet></list>=0A+</div>=0A+<= div effect=3D"fade-in">=0A+<list><bullet>The Brightness of the Stream Deck<= /bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><bullet>Time= Tracking</bullet></list>=0A+</div>=0A+<div effect=3D"fade-in">=0A+<list><b= ullet>Opening Other Pages</bullet></list>=0A+</div>=0A+</div>=0A+</div>=0A+= =0A+<div effect=3D"fade-in">=0A+<div class=3D"light-bg right-side">=0A+<exa= mple>=0A+Home:=0A+ - Index: 0=0A+ Type: pages=0A+ - Index: 5=0A+ Ty= pe: clock=0A+ Arguments:=0A+ - Hue: 90=0A+ - ClockName: "Xdebu= g"=0A+ - Index: 10=0A+ Type: brightness=0A+ Arguments:=0A+ - Le= velLow: 10=0A+ - ImageLow: "bright-000.png"=0A+ - LevelNormal: 50= =0A+ - ImageNormal: "bright-050.png"=0A+ - LevelHigh: 90=0A+ = - ImageHigh: "bright-100.png"=0A+ - Index: 11=0A+ Type: litra=0A+ A= rguments:=0A+ - 0: "4000,25"=0A+ - 3: "6500,80"=0A+ - Index: 13= =0A+ Type: command=0A+ Image: "lock.png"=0A+ Arguments:=0A+ -= Command: "/home/derick/bin/obs/lock.sh"=0A+</example>=0A+</div>=0A+</div>= =0A+</slide>=0Adiff --git a/slides/iot/the_internet_from_the_it_crowd.jpeg = b/slides/iot/the_internet_from_the_it_crowd.jpeg=0Anew file mode 100644=0Ai= ndex 00000000..18be884c=0ABinary files /dev/null and b/slides/iot/the_inter= net_from_the_it_crowd.jpeg differ=0Adiff --git a/slides/iot/varying-light-s= moothed.xml b/slides/iot/varying-light-smoothed.xml=0Anew file mode 100644= =0Aindex 00000000..70e0f967=0A--- /dev/null=0A+++ b/slides/iot/varying-ligh= t-smoothed.xml=0A@@ -0,0 +1,6 @@=0A+<slide>=0A+<title>Varying Light Smoothe= d</title>=0A+=0A+<image filename=3D"ha-luminance-both.png"/>=0A+=0A+</slide= >=0Adiff --git a/slides/iot/varying-light.xml b/slides/iot/varying-light.xm= l=0Anew file mode 100644=0Aindex 00000000..5918ef53=0A--- /dev/null=0A+++ b= /slides/iot/varying-light.xml=0A@@ -0,0 +1,6 @@=0A+<slide>=0A+<title>Varyin= g Light</title>=0A+=0A+<image filename=3D"ha-luminance-non-smooth.png"/>=0A= +=0A+</slide>=0Adiff --git a/slides/iot/wishing-tree.xml b/slides/iot/wishi= ng-tree.xml=0Anew file mode 100644=0Aindex 00000000..54bd8244=0A--- /dev/nu= ll=0A+++ b/slides/iot/wishing-tree.xml=0A@@ -0,0 +1,23 @@=0A+<slide>=0A+<ti= tle>Christmas Tree</title>=0A+=0A+<div class=3D"light-bg left-side">=0A+<im= age filename=3D"iot-wedding-tree.jpeg"/>=0A+</div>=0A+=0A+<div effect=3D"fa= de-in">=0A+<div class=3D"light-bg right-side">=0A+<image filename=3D"iot-we= dding-tree-switch.jpeg"/>=0A+<blurb align=3D"center">The "Easy to Reach" Sw= itch</blurb>=0A+</div>=0A+</div>=0A+=0A+<div effect=3D"fade-in">=0A+<div cl= ass=3D"light-bg right-side">=0A+<break lines=3D"2"/>=0A+<blurb align=3D"cen= ter">Now Automated</blurb>=0A+<image filename=3D"ha-tree-lights.png"/>=0A+<= /div>=0A+</div>=0A+=0A+</slide>=0Adiff --git a/slides/iot/zigbee-network.xm= l b/slides/iot/zigbee-network.xml=0Anew file mode 100644=0Aindex 00000000..= 957d5f10=0A--- /dev/null=0A+++ b/slides/iot/zigbee-network.xml=0A@@ -0,0 +1= ,15 @@=0A+<slide background=3D"ha-zigbee-network.png">=0A+<title>Zigbee</ti= tle>=0A+=0A+<break lines=3D"21"/>=0A+<div class=3D"light-bg">=0A+<break lin= es=3D"1"/>=0A+<list>=0A+=09<bullet>Coordinator: Controls the network</bulle= t>=0A+=09<bullet>Routers: Mains Powered Tech, with forwarding</bullet>=0A+= =09<bullet>End Devices: Battery Operated Sensors</bullet>=0A+</list>=0A+<br= eak lines=3D"1"/>=0A+</div>=0A+=0A+</slide>=0Adiff --git a/templates/defaul= t/sub.ezt b/templates/default/sub.ezt=0Anew file mode 100644=0Aindex 000000= 00..da47e236=0A--- /dev/null=0A+++ b/templates/default/sub.ezt=0A@@ -0,0 +1= ,2 @@=0A+{use $node}=0A+<sub>{$node->nodeValue}</sub>=0A