[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 &amp; 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/>&#1=
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() &amp;&amp; topic.Value =3D=3D payload {=0A+     =
 if topic.Type =3D=3D "brightness" &amp;&amp; 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", &amp;p.actions)=
=0A+=0A+  opts.OnConnect =3D func(c mqtt.Client) {=0A+    var subscriptions=
 []MqttSubscription=0A+    viper.UnmarshalKey("mqtt.subscriptions", &amp;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() &amp;&amp; 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() &amp;&amp; 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