 All right everybody we are back. We have cam talking about My house runs on net. You did an awesome job last year showing all the awesome things you were doing with the microcontrollers and Raspberry pies and all the sweet things so we can't wait to see what you have store on for for us this year. Oh Wow, so yeah, I have to live up to the expectations of yourself You drop the mic once you got to do it again So it's in the future. I need to make sure I don't do nearly as well, right? So, yeah, like Javier said, my name is camsoper. I'm a senior content developer here at Microsoft I'm just gonna jump right in with some slides There we go, so If you're anything like me you have a ton of devices Running in your home network that you know you plug into your house and they do house stuff home automation stuff IoT devices, I have a ton of these devices I have Switches I have contact sensors temperature sensors humidity sensors Relays thermostats. I have the gamut and they talk on all kinds of different All types of different protocols some use Wi-Fi TCP IP over Wi-Fi some use Z-Wave and ZigBee which are proprietary home automation protocols so I Have all of my devices at home Centralized through a home automation hub and there's lots of different home automation hubs. There's smart things. There's Kasa There's used to be Lowe's Iris. I landed on Hubitat Elevate now like most home automation hubs Hubitat Elevate is a It's a device that is the whole purpose is to integrate and orchestrate all your TCP IP Z-Wave and ZigBee IoT devices Now one of the main reasons I went with Hubitat is it's very similar to smart things It was actually started by former smart things engineers. So that means it has broad market support There's lots of devices and and apps and stuff that you can you can make work with Hubitat Maybe it wasn't designed for Hubitat Maybe it was designed for smart things but you can get it working with Hubitat pretty easily and then on top of that smart things has a really great open source community that A lot of that open source community when Hubitat became a thing picked up and went to Hubitat So there's this this whole open source community that shares device drivers and automation code One other advantage of Hubitat Elevate is that it does local execution This is an advantage over smart things where smart things is all cloud-based and not all cloud-based mostly cloud-based and The final reason I love Hubitat is it has a really easy restful API I can interact with I'm going to show you that here in just a second The downsides to Hubitat. Well, just like smart things it uses an obscure programming language Not many people have heard of it. It's called groovy. I usually when I give this talk There's always a few hands that raise they say. Oh, yeah, I know groovy To me it looks I'd never heard of it before to me. It looks like Java and Python had an ugly baby I'm not crazy about it Along with that obscure language we have a real lack of tooling Hubitat has kind of an integrated Kind of an integrated IDE and a browser and it's not it doesn't have any anything really in far as far as features go including Debugging there's no debugging So if you need to if you need to write code like custom code for Hubitat and not just like you know the built-in apps There's no debugging model. You just have to rely on on logs But you mentioned you might remember I mentioned a little bit earlier That Hubitat has a really cool restful API. I'm going to take a look at that real quick. So digging into The apps installed on my Hubitat its API is implemented as an app that whitelists the devices that are available to it and Then it just exposes Everything via a restful get request. So I'm going to paste in this This URL Into postman and it gives me a list of devices If I append a device ID onto the end of that URL It gives me the details for that one device and Then I can append commands like for example, I can say on and turn my bulb on Or I can append off and turn it off Okay, so I've got this really great mechanism that I can use to query the Hubitat device for information on my various iot devices that are integrated into it And I can send commands. I can turn things on and off and set levels and so forth What about getting notified from Hubitat Is there any great way that I could set up a process that could get notified when things happen in my Hubitat network? Well, it turns out there's an undocumented feature and that undocumented feature is a Web socket I've got a little browser extension here that shows that if we attach to this web socket We get events surfaced with the type of event The value of the events in this case open or closed and the device ID that caused the event All right So I have an API that I can send commands to and query information from and I have a web socket that I can attach to and Watch for events So inspiration struck I Realized that I could use that net core to build a framework around Hubitat's maker API and that web socket the event socket This would enable me to use dotnet's mature tools like visual studio Give me full debugging support and enable me to consume new get packages as well as give me a platform on which I could build anything I could imagine I could integrate with Azure. I could integrate with whatever devices. I wanted I Called this project puppet now. I'm not crazy about the name puppet I was originally going to name it puppet master The problem was whenever I would commit code to get hub I would type get push puppet master master and I'd hear Metallica, right, right, okay? So now that I've gotten that out of my system. Let's talk a little bit about how the tap works So I'm not have to have puppet rather so when puppet starts up it connects to Hubitat over that web socket I showed you earlier and it starts watching for events now here comes an event The front door open so that's going to be a contact sensor That's sending it's the type of event is contact and it is sending a value of open. So puppet is is Puppets watching that that web socket and when it sees a contact event from the front door that says open it looks in puppet Dot automation dot DLL because I have this assembly this class library that it Reflects over right it uses reflection and it looks for any class that implements an interface. I call i automation That also declares through attributes. Hey when the front door Experiences a contact event. I want to know about it So it finds all the automations that do this. Here's an example puppet automation front door stuff And it calls that handle method. It calls the handle method that's implemented by i i automation Right calls it. It's a task. It sets it up as a task and lets it run to completion Now while that task is running to completion. It can do all kinds of things, right? It can interact with Hubitat over the maker api It can go out to azure aws other iot devices wherever it can do whatever whatever you can do in dot net core you can do In in one of these in this handle method So It sits there and runs the completion running to completion means it could mean sub second or it could mean 30 minutes or an hour even right? We might we might just want to wait to see if stuff happens um if we're in a wait condition And another event comes through with that same Contact sensor. We're going to fire off the same handle method It's actually going to kill the one that was already running It's going to cancel it in flight kill everything it's doing And start up a new one and let that one run to completion All right, so let's see it in action Um, I have here in visual studio Let's look very quickly at my project. This is the puppet project It's these three projects right here. And then I have another one to demo today puppet executive and puppet common puppet executive is like the It's the brains. It's it's it's it's what handles, uh, you know listening to the event socket and It's it's the it's the program.cs. It does all the work puppet.com is shared Shared class libraries that go across puppet.automation and puppet.executive and puppet.automation is where we do all the neat stuff This is where we just add classes Here i'll show you a really simple one this is This is about as simple as it gets this is a automation that when I open a contact sensor turns on a bulb so Right off the bat. We've got this class all it does is implement this automation base class Automation base implements iautomation and then it adds a few other things. It does some stuff in the constructor initializes some fields and and Generally makes life easier for me The other thing that we do Is you see I have an attribute up here called trigger device and that trigger device is um Is specifying two things the first thing it specifies is that what I call the mapped name of the device I have a json file here That is a map of friendly names to device ids on hub attack So my multi-sensor that i'm going to use for demoing here is device id 2 um And then the other thing that we tell it is what capability we're looking for So if it's a contact event and if it's a contact event, it's going to be open or closed If it's a motion event, it's going to be active or inactive If it's a switch it's going to be on or off All right, so we implement automation base and we have an attribute that that tells puppet Hey, this class this is interested in multi-sensor events that involve contact All right So the very first thing that happens when this um when this class gets newed up You notice we've got a uh, we've got a switch relay device. I call it a switch relay device It's just on or off right this means a device that supports on or off Um So we have a switch device here that I call bulb a field and I have a Method called a knit devices a knit devices is actually an abstract method inherited from automation base It gets fired off before anything else and the whole idea is that we're going to admit our device fields So you can see I have a a hub field. Um, that hub field represents the hub attack collection of devices And a method called get device by map to name return it as a switch relay and the name is demo dot bulb So that gives us a reference to our bulb. Why am I doing this in a knit devices and not in the constructor? Well, you'll notice Get device by map to name is awaitable and you can't call awaitable code easily from a constructor. So Um, I I made an init devices method that gets called before handle All right, so then the handle method this is what i automation brings to the game and i automation Well, uh, like we talked about implements this i handle. I'm sorry influence handle and handle goes off and runs the completion and um We have a object. We have an object that represents the event that triggered this, right? That's handled by the base class if that event is an open event In other words, if it's open as opposed to closed, we're going to turn the bulb on otherwise We're going to turn it off. All right, so let's run the code Pop this up to full screen and then i'm going to work a little movie magic And give you an overlay All right, so here's my multi sensor right here. This is the device id Um, sorry for the lighting my window is right there and the sun's shining right in. Um So when we open this my bulb should come on Sometimes it has to warm up And it was giving me trouble earlier today too. Luckily, this is the only demo I have that depends on this Come on wake up Oh, there it goes And the bulb should come on bulb comes on. All right And then bulb goes off. We'll close it bulb goes off. There we go So that's that's the super useful a super basic use case rather Um, but let's expand on that just a little bit Um, this is this code is very similar code that I use in my house So I have um a walk-in pantry and I've got a light in the pantry and a light switch And I've replaced that light switch with a z-wave enabled light switch So the idea is that when we open the pantry door, we want the pantry light to come on Well, that's easy enough on and off. We've already got that code written But there's a problem and that problem is teenagers. I have them Um, and I can't get rid of them So they leave the door open all the time and I want the door closed Uh, so what I the the way I've accomplished this is I actually have a public speaker um, remember I mentioned habitat has a great open source community and one of the great things about that open source community is um, that they do all kinds of neat stuff and Hubbitat supports text-to-speech through premium sonos speakers Uh, the community said, yeah, that's not good enough for us and they invented a mechanism that you can use to actually Send text-to-speech to good old-fashioned vlc So, uh, we'll just test it right now test Test there we go. Let's give it another test Actually, I was thinking about forming a band with uh, this text-to-speech Check baby check baby one two three. Yeah, I think it'll be fine. Um All right, so I've got that speaker device And what we're gonna do is We're gonna make a field to hold it hold a reference to it. Whoops There's our initializer And down here, we're going to add just a little bit of code We're gonna I've got a method that's part of the base class called wait for cancellation async where it'll wait Uh, however long we want it to in this case. I'm going to say five seconds in the real world I wait five minutes, but for demos we're going to say five seconds and then we're going to speak Please close the door. All right. Let's see what happens. There we go Hopefully my sensor cooperates this time Come on hurry up connect to hubbitat. There we go One two three Please close the door. There we go. All right. So well, let's do as it's do as we're asked All right. Uh, what if we close it if we close it before? Remember we have that that that, um We have that wait in there. We're waiting five seconds, right? So what happens if we close it before the five seconds? So Open bulb comes on close it Do we hear anything we hear nothing? So the the running task was cancelled during that wait all right So, um, as you can imagine that speaker that announcement speaker that I have I have a raspberry pi sitting out in my kitchen That's connected to a speaker. I runs vlc the command line version of vlc And it just sits there 24 7 and it's my announcement speaker And as you can imagine it's a handy tool, especially if I have kids which I do um I work from home and uh the One of the problems working from home is It's hard to get quiet frankly. Sometimes I'm in a meeting or I'm giving a talk like this for example And they're being noisy. Uh, usually it involves wrestlemania. Usually I can hear sounds from the kitchen Hulkamania brother, you know, I don't know that I don't know what's wrong with them. They're I I've given up anyway um I have switched to this display I have a little remote control Like this here we go. There we go. Now we can see it I have a little remote control just like this one with four buttons and they each can Be pushed or held. So there's pushed events and held events of values one two three and four So I have some remote control code. This is the actual code I use on my home network right here um Let me switch back to my there we go. So this is the actual code I use on my home network to drive a remote just like that Um, you can see we are watching that remote for both the pushed and held capability And it's actually a pretty simple. So there we're an idiot. It's a pretty simple. Um handle method It's just a switch. I'm using c-sharp 8's tuple Uh tuple evaluation here for the uh for the switch Um, so we're switching based on the value and whether or not it's a button pushed event because I said we're watching for pushed or held So logically if it's not pushed it's got to be held and I've got five of five different phrases here that I can speak Um one if I just push button one your father requires quiet Please all the way down to I I can push button for or I can hold button for and I think I'll just show you what those do Connect connect connect, okay So we'll push button one Your father requires quiet, please. Okay. So generally that gets what I need done. Um, however, sometimes I have to resort to pushing button for Whatever you are doing. It is frustrating your father. Please correct it now or there will be consequences And if that still doesn't get them to shut up Then I have to hold button for I said there will be consequences big consequences All right So that's just kind of scratches the surface over some of the cool things that I can do with puppet Um, I think probably the the coolest use case though Has to be uh building my own iot devices and automating them Um, and let's actually look at an example of that This right here is a garage door controller. It doesn't look like it yet. Um, this is this is I actually took this picture yesterday This is a raspberry pi with a little breadboard that I soldered together All that breadboard does is it just exposes uh some pins in a certain order on a on a header That's all it does and I've got it connected to uh connected to a relay On the other end of that relay I've wired it into my garage door switch um and There's the device as it sits on top of the refrigerator in my garage right now So we've got that relay connected to the garage door Now the idea is that I can just like pushing the button I can essentially automate pushing the button right I can close that circuit and uh and cycle the garage door So the way this garage door opener device is going to work Is I've got a virtual garage door driver that I've written in habitat and a physical contact sensor on My actual garage door Now when I open the garage door like if I go push the button or if I push I've got a remote here that I can push to if I It's like in my car like if I come home and I push the button in my car The garage door opens the relay sensor flips from closed the physical sensor switches from closed to open Okay puppet sees that right through the event socket and it goes to my virtual garage door driver which Previously said it was closed and now says hey You're open it calls a method on it called confirm open says you're open now So if it flips its status to open Now that handles if I push the button if I manually open the garage door But what if I want to send a command to habitat through the api? uh to Cycle the garage door, so I'm going to send a closed command So if I send the closed command what's going to happen is when I send the closed command to my virtual driver It's going to set its status to not closed but closing Puppet is going to watch for an event called closing and when it sees that closing event It's going to communicate with the raspberry pi and say hey cycle the garage door Which cycles the garage door And then the same flow that we saw earlier happens where we flip that contact sensor to closed Puppet sees that and notifies the garage door that hey you are indeed actually closed now All right, so let's I know i'm running low on time. I'm going to do this demo quickly and hopefully we'll still have time for a question or two So i'm going to drop this project this class out and bring these two in The first thing i'm going to show you is just my remote control. I just reconfigured it So now just button one and two Open and close respectively. All right The let's show you the virtual driver real quick. This is hub attack code that I had to write. It's um, it's groovy It's ugly. I don't like it But you can see that we are basically declaring here at the top that we are we we implement contact sensor and Garage door functionality in other words. We uh, we support open and close commands and we also support open and close statuses and we also Define our commands confirm open and confirm close that I talk about And then down here's just the implementation of all that. There's really not a lot of logic It just does exactly what I said on the slide um Let me go back to my actual garage door There it is We're going to put him down. Whoops. Nope. I don't know where I wanted to put him. He just wanted to go away Now Windows right down. There we go. I want him down there. We're going to leave him right there Um, this code up here the garage door controller hub attack code or a puppet code rather Um, it watches that contact sensor that I told you about it also watches the garage door for door capabilities Remember I said we're watching for opening or closing. That's what we're watching for I also have another attribute here called run per device run per device says, okay We're going to allow multiple instances of this handle method One per device that's listed here by the trigger devices That was just so I didn't you know end up with like a race condition Uh, we annit the virtual garage door controller what we're watching But remember we're watching the garage door contact for contact events and we're watching the garage door for door events So down here in the handle we say, okay if we're not if we're not talking about the garage door So we're talking about the the the the sensor right the open or closed sensor If it's an open event we send confirm open to the virtual driver. Otherwise we send confirmed close um, and if And the other case if the event if it's a door event if it's opening or closing Then we just send a cycle command to the raspberry pi and that raspberry pi command The way we're doing that is we're just sending a message to azure service bus right Open sesame And then the raspberry pi code over here scrolling down getting to the good part is If the message is open sesame we cycle the door for three seconds I've got to cycle the the relay for three seconds, which tells the You know where I'm going with this. All right. Um, let's run this And as a special treat we have my actual garage this whoops We're put that up there and Yeah, you know what changed my mind. I'm going to put That down No stop window management is hard y'all um There we go, uh, we also have my overlay down here. So, uh, let's test it out the first thing we're going to do So I got this remote. This is just like the one I have in my car. I'm going to push the button All right, the garage door is opening. Hope it should see that it does see that And you can see down here on the lower right down here where I'm got my mouse It now knows the garage door is open What about going the other way? Well, remember the code I wrote button two should close it So let's hit button two if you watch the window in the upper left. That is the raspberry pi code And you're going to see where it gets the message cycling door and There goes my garage door And that ladies and gentlemen Is our presentation for today The choice of music is spot on sir Sorry Javier. I can't hear you. This choice of music is spot on Thank you, sir So Believe it or not. We don't have any questions because not because People were just like, oh my gosh, this guy rocks Again, you you you pulled it again, sir like last year. We were like, uh This is amazing. People were wondering where the code Is on github. Do you have that something right there or is it proprietary? So I'm gonna I'm gonna throw that slide Oh, wait audio you get to hear the music music again. Um I'm throwing the slide up right now. It's github.com Slash camsoper slash puppet or if you take a snap of that slide real quick that qr code will get you there Sweet awesome. Thank you so much cam. This is a great presentation Like always I really appreciate taking the time to share your your skills and your passion for all this with us So everybody we have erin Coming up to talking about actors and aka.net. So we're going to switch to this To the slate here Call him up and we'll be right back. So if you don't hear us, don't freak out We're just switching out speakers. Talk to you guys in a bit