 Okay, well, hello world. I'm Timmy, let's go to the next slide. Also known as SourceQt on Twitch and pretty much every other social media network out there. I'm going to give a brief introduction about myself. I work as a consultant at Centric and pretty much hired by big organizations, financial organizations, governmental organizations to build websites, web applications. Using C-Sharp, ASP.NET, .NET Core, Angular, all that kind of stuff. And outside of work, I am a live coder here on Twitch and I run a meetup with WebExr. He's another live coder. We got to celebrate that. I love seeing the live coders joining us here. It's great to have you here joining us. Yes, it's a great community, the live coders community. During my streams and outside of work, I'm always busy with JavaScript and the modern web. The most cutting edge web APIs I'm using and we're going to use one of them today as well. Besides all the work and code, I have also a family with three daughters. A while ago, I was with one of them to her gymnastics practice. In the court next to where she was practicing, there was this golf ball game going on. And golf ball, if you don't know, it's a game. It's pretty popular here in the Netherlands. It's a bit similar to basketball. You have a hoop where you have to throw a ball in. And at the sideline, there were two people sitting there with one of those flip cards, score things. And I was looking at it and was thinking, well, I should build an app to do that. And since we're at an app, why not go all the way, add some arduinos and sensors to the thing and have it automatically count to the app. And yeah, I decided to build a proof of concept to see if it's possible. And I'm going to run through that proof of concept today. And there were some, sorry? This one? Where is it? This? Okay. There were some interesting things I had to solve with a web app running there. Since this support complex is like a big metal box and you have completely no reception in there. So yeah, the app had to work offline. And yeah, I came up with a list of requirements. It had to be a progressive web app with offline support. And since I didn't want to have anything to do with servers and backends and stuff, I decided to build it as a static website on Azure. And yeah, I need to store the data somewhere. So I decided to store it on an Azure table using an Azure function and using Arduino for the sensors. So when drawn into a picture, it will look like this. And I'm not going to build the entire app today. I'm going to focus on the Azure side of things, how to set up the serverless hosting and backend. And I'm going to demo everything that's going on. And yeah, I've built the app almost entirely. I was hoping to do everything on the stream, but then I think we can do an whole day building this application. Yeah, and that's about all the slides I have. So let's close this down and go into Visual Studio Code. One of the great things of Visual Studio Code is that you can do pretty much everything. Everything with Azure, but we need from the Visual Studio Code. There's an immense amount of extensions you can use. Even for the Arduino, I built everything from the Arduino from the Visual Studio Code. So I'm already logged into my Azure account here. And first of all, I need to have a storage account set up. So I'm going to name it, let's call it PWA serverless. And for some reason it doesn't, like, you can do it a million times. New storage account PWA serverless. Luckily I have this already planned up front and I have one set up here. Normally it will take a few minutes to set it up. I've made already, created one already. Got a backup one here as well. So to deploy a static website, you can just deploy your website. I have the website built already, so you can just go to deploy a static website. It's going to be removed. And you can select the folder you want to deploy. Now normally the first time you are, when you create this storage account, you will get a message if you want to enable the static website. There's some things in there already. I'm not going to overwrite it since then if anything else goes wrong, it might not work anymore. But this will copy all the files to my Azure account and to this $web folder. You can see everything, all the files are in there. You can go and browse the static website. And this is the website I have created. It's a small proof concept as I said. So we can start a new game. And the funny thing is, let me add the second side over here. I've got a camera pointed at the back of me, where I have the Arduino setup with, well, this proof concept cup with the sensors in there. I never turn it on. I can see it's loading now. And as soon as it turns green, it's ready to receive the Bluetooth command. So now I can connect from the website that's running on Azure and pair it. And as soon as the lights go off, I pair it. I had a ball some here, but I lost it, so I'm going to. Now as soon as I hit, as the sensors are broken, it sends a notification back to the website and updates the score. Let's turn it up. I'm going to show how this works in a bit. Now we need to store that score somewhere. So we're going to add an Azure function for that. So you create a function app or an advanced app. Now, when you create a function app, this will also create the storage for your, your function. And since we already created the function, the storage, we do not need to create it again. Also, when you create the function first and the storage is created, you have a different version of storage. And then you cannot deploy your app to that storage anymore. I think it's the V1 that is created when you create a function app this way. And if you create the storage from the storage extension itself, then you get the V2 version, which you can enable the web app on. So again, to create a web app, you can just see if this works. Server, you can select an OS plan. Well, again, for some reason it's broken. I just did it right before I'm in live, but some is broken, but I have a backup plan already in place. So we end up with this situation where you have a project and you have the functions here as well. So I've created a new function already. This is an HTTP trigger, which means that if you do an HTTP call, you can have this function handled at the HTTP call. This will give you a default. Since I'm a JavaScript guy, I created the function in JavaScript and you get this folder in your project and then score the function with an index. Oh, by the way, forget something. I also added bindings here. And one of them is a table binding. And again, it's all stored inside your project. These are the bindings. We have an input table. I forgot to show that as well. You can create tables from within this extension. I create a scores table and any data I send there will be stored in that table. So this is just the binding for the input and this will provide you with the data from that table every time the function is run. I was planning on doing an output binding as well. But again, it took me a while to figure that out. It didn't work and there is a difference between the JavaScript version and the C-sharp version. In C-sharp, you should be able to use the output and update data from there as well. In the JavaScript version, you cannot update your data. You can only add data or get data. And I wanted to get data if I request some data from the function. So this is just going to get the input table. If I give it a match ID, it filters the data and returns only the score if it found that match ID. Otherwise, it will return the entire contents of the table. Now, to update the data, I had to write a little bit more code and eventually used the insert or replace entity function on a table service to update the score. Hopefully, in the near future, you can just do an insert or replace with the output binding. So then all this code is not needed anymore. Now, one great thing of doing this in Visual Studio Code is as soon as you create this function in Visual Studio Code, you get on the debug tab a link where you can add breakpoints and run it. I'm going to run this from the command line now because it's just a bit faster. So in FuncStart, this comes with the function tools which are installed and then you can just use command lines tools to update things. And you get a URL. It knows it has a get and a post. And you get a URL you can call on local host. Now, I've got Insomnia running here to test the API. I really set this up. If I send just a get request to that URL, I get all the data. And if I do match ID equals 124, we should get only sensitive. Yeah, we get only 400. There's the score of 400 with that match ID. And the same for the post. You can post data from here as well. So we can test this. And if I run it from the debugger, you can hit breakpoints and debug your functions from the extension as well. Then deploying the function is as easy as deploying the website. You just hit deploy. You can select the function app you want to deploy to, which again somehow is broken. And then this deploys your function into the cloud. And you can copy that URL, run it. And if I go to Insomnia again, I've got it running already. So I can do the same thing. I will get pretty much the same data since it's using the same storage in the back end. How are we doing? Yeah, then the last part is the website itself. There are a few things that are interesting in this. Let me close some of these windows. It's a progressive web app, which means it can install a service broker, which runs in the background and that can do all kinds of crazy things, like intercepting requests from the client to the server, which means that you can store those requests. And this can be any request, even CSS or images or whatever. And those are stored on the client. So when there's no internet connection available, you're offline, the service worker knows that you are offline and can return the data from the cache. So the website keeps on working as normal, although there is no internet connection, which I'm going to demonstrate. Then we have the Bluetooth part. So I have this Bluetooth service, which isn't, well, to get it to work the first time was pretty hard. You have to get all these IDs in the right order and then do all kinds of awaits to get to the Bluetooth device, connect to it, get all kinds of characteristics. And then once it's done, you can just wait for it to handle an event. So when these sensors are broken, it sends an event, and then this just handles that event and updates the score. Which is pretty cool. Now once the score is updated, it is sent to the score service. And I've got two versions here. By now it's in the most advanced mode, so to speak, is not sending it directly to Azure. It's storing everything inside an index DB. So every time a score update comes in and something had to be sent to the server, it's just storing that event. But it's also emitting an event that says Save Data. That event is handled by the service worker, or actually handled outside of the service worker and then sent back to the service worker, which will catch that event and tries to send that data to the server. Now if there's no server available, it would just catch that event. And as soon as the service worker goes back online, it has a connection again, it will sync that data automatically. So let's see if we can demo that. If I go back to that page, let's try this one. This is the one that is deployed to Azure. Move it side by side again. So we are starting a new game. I'm going to grab the network tab. So now we are online. So if everything goes well, it is ready to receive the connection, we pair. And again, this is all running from a website, nothing in between. And but now it's broken. Sometimes it does that. It seems to be a desktop thing, by the way. If you run this on your phone, it will just run fine. I've tested this a million times and it's broken again. It's wonderful. But luckily I have added two buttons here, which should help us. So for some reason, let's try the local host version. That's still running. Yeah, so this one is working. And this should send a score to that URL into Azure. And if we look into the table here, we should see that, I think it's the last one here. It got an ID of 936 and it has a score of one, which is actually incorrect, but it's probably the demo gods. I forgot to make some offerings. But when we go offline, we should still, the applications still work. Even if I refresh the page, it still works. We should be able to connect to the Bluetooth. You will get errors in here as well, because it cannot send anything to the server. But that doesn't bother the application. So we can add scores, and they won't go anywhere. But if we go to the application tab, and have a look at the servers, index DB, we should have a lot of scores in here that are stored there. And as soon as we go back online, we should see a request going off to the server with all these events. 406 was a score of six. So we go here, refresh. We should see 406 with a score of six. So it has sent this to the server as soon as we went back online. Now, one last great thing you can do here is adding this plus icon, which installs the app on your desktop. At this point, it starts to look like a native app. Right now, it's behaving like a native app. It's using Bluetooth native functionality. It's not a real native app. That's why I added the quotes. But it's behaving like a native app. And that's what service workers are going to bring you. And let me check if I told everything. Yeah, I think that's about it. I had to go fast. I had to make up some time. Let's see, I had one more slide with my PowerPoint. So what we did, we deployed the app to Azure Storage. We hooked the function to that. That stores data into a table. We can keep the data offline. We sync data when we went back online. I didn't show you the Arduino code, but it's in the same project as well. And everything is done from within Visual Studio Code. And that's all I had. Yeah, if you want to have a look at the code, by the way, it's on my GitHub. You can download and try it yourself. I don't have the schematics of the Arduino device there, but it's not that hard to figure out if you know anything about Arduino. That was really cool. I love going from a prototype of a coffee cup. Yes, well, that's the best way of doing it. We have coffee cups. Well, just prototype something. Oh, my gosh. So neat. And folks today in here, looking at the cup and wondering if technology has gone too far. You know, people have Bluetooth-enabled water bottles. It's all right. Yes, it's how things work nowadays. So do you actually use the app to keep score? No, I haven't. You haven't tried it in the real world. I was just watching that game at one point. Well, maybe it would be a great demo and prototype to do something with functions and Arduino's and get everything together and build an app that is not too complex to understand. Right, like FIFA, right? The folks that manage football, the World Cup, right? They put sensors around the goal mouth. So they know when the football crosses the end line. Right? It's the same thing, but in a coffee cup. Yes, although there are some issues. Sometimes when you throw the ball in and you don't go exactly through the place between the sensor, it doesn't count it. If the ball bounces out, it counts it twice. So it's not perfect yet, but I'm working on it. Very cool. And I want to make sure folks get your Twitch account there. Make sure you check out twitch.tv. Throw a follow over there. Really great stuff. Thank you so much for joining us today. You're welcome. All right, and we'll catch you next time over there on your channel. Thank you. Have a great day. All right, we'll see you.