 All right, well, welcome everybody to my session about entitled growing in the cloud. This talk is about my journey to create, believe it or not, hot sauce using IoT messaging, Micronaut, which is an open source Java framework, and some other cloud technologies. And I used all those to automate and monitor seedling growth to help me grow chili peppers to create hot sauce. So a little bit about me. I am a developer advocate, and that means I get to talk to developers, learn from developers, a little bit of evangelism, talk about some of our technologies and products to them, but mostly listen to them, gather their feedback, gather their experience, and take it back to our engineers and our project managers to help make better products. You can find me on Twitter, YouTube, all those places in the social world. My blog is recursive.codes, as well as my GitHub. So I'd like to make a promise to you, and for the physical and virtual attendees in this session, I will show you how I used microcontrollers, sensors, and the cloud to create what I call the world's greatest hot sauce. Of course, that's based on my opinion, but also the feedback of some friends that I've shared it with. So it's not just mine, but mostly it's my opinion. So the motivation for this project. Personally, myself, I had a little bit of a rough year in 2020. Not just me then, okay, yeah. So we were all kind of stuck at home, right? And a lot of people were used that time and that challenge to take on new projects or new kind of hobbies. A lot of people, for example, were making sourdough bread and all kinds of fun things. But for myself, one of my passions is cooking and spicy food. And I just absolutely love cooking. It's always been one of the things that kind of keeps me motivated and just something I love to do. So I was at a farmer's market in my town. Of course, oh, you know what? If you don't mind, it makes it easier to not keep breathing my own air while I talk here. But of course, I was masked up properly and socially distanced and all that at the farmer's market, except for the one lovely old lady who insisted on licking her finger to separate the bags, which I politely asked her not to. But for the most part, things were safe and saw these beautiful peppers that you see here. And I thought, you know what? I love hot sauce. I love spicy food. I'm going to try to make some hot sauce. So I bought a bunch of these peppers and brought them home and chopped them up, mixed them with little onions, little garlic, carrot, things like that and threw them in a jar with a brine, saline solution of brine and left them to ferment for a few weeks. Come back a few weeks later, blend it up, mix it with a little vinegar and bottled it and there's my hot sauce. So that was 2020, right? Well, 2021 came around in the late winter, January, February timeframe, and I said, you know, I want to make hot sauce again this year, but I want to up it, I want to up the challenge for myself and I want to actually grow the peppers myself from seed. Now, I've dabbled with gardening a little bit and I'm certainly not a master horticulturist or any gardener or anything like that, but I thought, I want to give this a shot and I thought, well, what else can I do? How can I up this even more? And I said, well, maybe I can mix it with another one of my passions and obviously another one of my passions is technology in the cloud and microcontrollers and things like this. So I said, okay, what if I actually create a system to help me monitor and automate the growth of these peppers? You know, just a little simple system that would help me do this and so the result of that is what I'm calling project green thumb and that's what we're here to talk about today. So I did my research and I identified these five separate metrics that I could try to control throughout the growing process and this is, again, based on some research, doing some reading, determining what's the best environment, what's the best temperatures and light and humidity and moisture, what is the best environment to grow these pepper seedlings in? So I came up with the objectives that you see here. Daytime temperature, 65 to 80 degrees, which is 18 to 26 for those people who use that weird scale. Soil temperature, moisture, humidity and light. Light being measured in lux. So that's my objective. Let's talk a little bit about the architecture just to give you an overview of what I decided to do. So I said, as I said, I was going to use a microcontroller and some sensors to monitor and automate the process and what I figured I would do is collect the data on the microcontroller, broadcast that to a messaging queue in the cloud, in this case using RabbitMQ and then consume that messaging queue with an application that could be used to visualize real-time data as it happens as well as generate some reports and things like that. Now, I know it's all the rage to use the microservices these days but I didn't use a microservice as we probably know there's really nothing wrong with using a monolith here and there, especially when there's something like this where it's not really suited. And then the microservice or the application would also persist that data to the database. So before I go on, since we're at the open source summit, I want to talk a little bit about why open source matters to me, just a little deviation here so for me, open source is kind of like cooking, right? If you think about it, if you went to a five-star Michelin restaurant and you sat down and you had the best meal of your life and you went up to the chef afterwards and you said, hey, that whatever, that pasta dish was amazing. Could you share the recipe with me? At that restaurant, he might say, nah, it's kind of a secret, you know, but for the most part in my experience with cooking, cooking is kind of open source. A lot of people like to share recipes. They come up with this plan and you can build upon that plan. You can modify that plan. You can make it your own, right? So open source is very similar to that, right? We can take these projects that exist. We can build upon them. We can modify them. We know what's in them and we can cook our software. So lower hardware costs. For me, a project like this wouldn't be possible if I was worried about infrastructure. If I was in need of really robust servers in the cloud, if I had to pay licensing costs for hardware and things like that, it would just be cost prohibitive as a hobby project. It just wouldn't be able to happen. Now with open source, with Linux servers, I can deploy this on an always free tier of a cloud provider, a space oracle. But it really helps me to work on these kind of projects that I otherwise probably wouldn't be able to deploy. Obviously, this means lower development costs and time. I think that's kind of a no-brainer. Flexibility and transparency. So I think about a story that happened about 10 years ago. The team I was on at a firm building government software to using an off-the-shelf product, and Stephen knows what product I'm talking about, cold fusion. We used that quite a lot. And it was a rapid deployment, rapid development platform. It was very easy to use, low barrier to entry, but it was proprietary. It wasn't open source. We had made a decision at one point to switch over to a more open platform, framework, more open source technologies. And really early on in our development cycle, I identified a pretty critical bug with encoding user input, which as we know is a pretty big deal. You don't want to use, display user input on a page without it being properly encoded and escaped. We can have serious security vulnerabilities. Well, I identified that issue. I created a source. I created a patch. I submitted it, and within two days that was merged and published into the next release of the framework. If we had that same issue with that off-the-shelf product, now, of course, they do worry about security vulnerabilities, but being a commercial product, they had, you know, Solaris, Windows. They had all these platforms they needed to support. And not only that, but really is it, does it affect enough people? And it just makes it much more difficult to, number one, understand that there may be vulnerabilities inside the product, because we can't look at the code, but to be able to patch and fix those and push those out into production. Finally, open source really kind of grew my career, you know. Being involved in some early open source projects and contributing to them really helped me network with some of the members of the Java community and other communities that I'm a part of. And just putting my own open source out to the world is a really good way to, it's kind of like a living resume for your own code, right? If you can just point somebody to your GitHub repository and say, here's what I've done, you know, it's a really good way to show people what you've done. So that's why open source matters to me. So I want to do a quick demo here. If you'd like to follow along, I'm going to show you up on the screen so you can see what's going on here. So I'm going to show you the actual system itself. And it's this little mess of wires that you see here. And let me pull that up next to it. So this is the actual deployed application running in the cloud on the right-hand side of the screen. And on the left-hand side of the screen, you see this little box with a little breadboard inside. There is a microcontroller down at the bottom, soldered to the breadboard. Now you see all these wire connectors here. That happened because I was giving this talk virtually a couple months ago. And in the morning I went to test it out and nothing worked so I had to cut it out and basically rewire the whole system. So I did it the quick way and just pieced them back together with these connectors. So this is a little mini OLED display, very, very tiny. Basically it gave me a way to have an instant feedback, instant results just by looking at it. There was a lid to this case. Well, obviously with these connectors it's hard to fit that lid back on. So that's why it's kind of loose and open right now. But there was a nice lid on it that when it was sealed, the only thing you could see is that little OLED display. So these wires coming out of the side here if I can grab them without knocking everything over up here. So these are all the different sensors attached. So this sensor right here for example is a light sensor and this actually reads light and displays the amount of lux in the light. This sensor here is a probe thermometer which was nice because once I had my seedling tray I just plugged this right in the middle of the soil and it allowed me to monitor the soil temperature. This temperature sensor here is called a DHT-11 and this allowed me to monitor the actual air temperature and humidity in the seedling tray. And finally this corroded sensor here is a water sensor. Now one would think that if a manufacturer was making a sensor that was intended to measure moisture that it would not corrode but apparently I learned my lesson and these sensors are more intended to measure like air moisture kind of thing like near maybe near a furnace or a freezer or something like that. Now they do make capacitive moisture sensors that have like a rubber coating on them and lesson learned I'll be using that next year when I come back to it but it did the job. Finally, this connection here if I can move this over slightly actually let me move the camera. So this is a regular standard electrical junction box but the special thing about it is inside of it there is a relay that allows me to turn the outlet on and off. So the purpose of this is to help me dilate the temperature within the soil and I did that with one of these which is just a heat mat kind of like a heating pad that you would put on a sore muscle but without the fancy fabric cover it's just like a rubber mat that plugs into the outlet and heats up your soil medium. Now of course I learned later on that they sell these with inline temperature controls but that's okay nothing wrong with doing it yourself and managing it yourself and of course it did keep the costs down this was only about $12 on Amazon so really nice way to regulate the temperature within my soil medium. Now plugged in combined with my probe thermometer that monitors the temperature I just turn it on when the temperature goes above or goes below a certain threshold and turn it back on when it goes well on and off depending on the temperature right so essentially I was able to automate the temperature of the soil that I was growing this in. Now you may ask yourself ask yourself why I didn't take it further and automate the actual moisture level of the soil and there's a good reason for that it's not because I'm lazy or didn't want to I did think about it I considered it maybe hooking up a pump or something like that where I could pump water into it below a certain moisture threshold but that was one of the metrics that I was a little less comfortable with automating because I don't have the experience I didn't know what the appropriate level would be so I figured well I'll collect all this data I'll see how it did and then next year I'll be able to enhance it with that knowledge that I've gained so yeah there's of course opportunities to go even further to automate more but sometimes less is more and that's the route I chose to go with so let me plug this in and show you actually how it works or show you it working so I'll plug this in and it's powered by USB so if we come back over here the OLED is still going to be pretty hard to read so what I'm trying to do now is connect to the hotspot running on my phone which let me make sure it's turned on and it's not because Android is kind enough to shut that off if nothing connects to it so I'll try that again now that my hotspot is running and we don't have to rely on conference Wi-Fi here it should connect up any second now and now it's connected and so I'll plug in this little LED and you can see that the outlet if I you probably see it in person here but also through the camera you can see that the outlet itself is on now if we look at the web page on the right here we can see that in real-time I'm getting data every second that's published to these real-time charts so my air temperature is steady at 73 degrees it just jumped a little bit really nice way to get that direct immediate feedback of the current air temperature this current values are shown at the top of the page kind of at a glance so you can see what's going on there soil temperature here is 72.5 degrees if we demonstrate the soil temperature going up you can see that the outlet was turned off the LED is now off so just showing you how the soil temperature actually works and it gives me that nice line in the chart to show me that the outlet went off it cools down a little bit the outlet will turn back on once it falls back below that threshold moisture level 0% obviously if I do take a little bit of water here we should be able to demonstrate that there we go so you can see that I've got a little water and I'm dipping the moisture sensor into that so you can see that it properly measures moisture in real-time and I do have this running an update every second for other purposes here at the conference but in reality I had it updating much less frequently at home because I don't need this real-time data for growing seedlings humidity 58% staying pretty steady and again the light level sensor is reporting pretty low light in this room but if I do expose it to some light we should see that jump quite a bit as well so we jumped way up over 500 there so that's how the system works essentially it allows me to control the soil temperature that we're growing in it allows me to monitor the moisture, the humidity air temperature, all those kind of things so let's jump back to the slides here now as someone famous kind of once said talk is cheap show me the code so from now on we're going to kind of basically be looking at the code behind the scenes and seeing how that works and I want to start out with the actual Arduino code so do we have we all experienced with Arduino we're somewhat familiar with it so essentially one of the awesome things about Arduino that I don't talk about at normal conferences although maybe I should is that the Arduino platform is open source it is the entire hardware and the software ecosystem the IDE that you use to program it it's all open source and that's really nice to me because it makes it accessible it makes it to me it drives the cost down because people are able to take those prototypes schematics for the boards and reproduce them at much lower costs so it really kind of keeps it as a very accessible technology for doing projects like this that's not to say there's anything wrong with Raspberry Pi and having a proprietary chip you know it has its uses it has its upside and downside but it's one of the reasons I really like working with Arduino now I shouldn't say I should also say that Raspberry Pi has come out with the RP2040 which is open source and so I can't fully knock them not that I'm knocking them but it's one of the benefits in the draws of Arduino for me so essentially Arduino one of the reasons it's very nice for projects like this is there's no overhead of an operating system or anything like that you essentially have one binary program that runs you flash it to the to the board and it you plug it in powered on and it runs there's at its very basic minimum there are two functions required in your code a setup function as that implies it runs the first time the board is powered on and allows you to do things like connect to Wi-Fi or establish you know system establish variables for your for your local environment and then there's a loop function and that loop function just runs continuously over and over until the board is powered off it's entirely single threaded although we can do things like interrupts and timers to kind of mimic multi-threaded type code but essentially it's just a single threaded loop that runs constantly if we don't want it to run we can put in things like delays to delay the frequency in which the function runs. So the two things I want to show you here well more than two but the main thing here is the fact that I'm using the Adafruit MQTT library and that allows me to easily publish to my MQTT server that's running in the cloud are we all familiar with MQTT I'm fascinated by MQTT so it's a it's essentially an open source messaging protocol and there are several implementations that allows you to do very lightweight messaging it was originally developed for the oil and gas industry believe it or not remote pipelines way out in the field they wanted a way to publish data from those that could be reliable very lightweight because obviously your resource constrained in remote oil and gas fields and so they developed this I believe it was IBM that developed the protocol for MQTT it's just basically publishing and subscribing it's not a durable Q so you're just publishing messages off into the ether if there's nothing consuming it they just disappear into the ether it's not like something like Kafka where you have a durable Q that is resilient that maintains your messages that are cued when the consumer goes offline so it's just publishing messages up into the cloud and really lightweight like I said and allows you to do things like this with IOT devices so down here on lines 50 and 51 is where I established my connection I'm not going to show you my credentials here because that would be silly of me but essentially I just create an instance of the MQTT library I have spilled water on your board over here sir sorry do you have a towel that's could be bad good times so sorry about that I will move that away from there what's your name again Colton you're the man appreciate your help alright so I created an instance of MQTT pass it my server my port my user and my password which also receives an instance of a wifi client so it knows how to what internet connection to use for that publishing and then I establish a readings topic and that is simply where I pass it an instant that instance of MQTT that I created here and then the name of the topic topics and MQTT are often times separated by a slash like that and it's just a pipe a channel that I'm using to publish all my messages to so skipping past some of this other code I come down to my setup method and essentially what I do here is I initialize the pins on the board and in this case I tell it what pins to use for what purpose so for example pin s0 I want to use as an output pin meaning in this case I think that's goes along with my monitor so it's an output it's something that I'm producing from the board input pins are pins that are used for inputs things like sensors and other devices that you can connect that input data into the system I set up my display I initialize my Wi-Fi connection and then we come down here to the loop function and this is where the cool things happen so with Arduino essentially you need to either read or write so you're reading from inputs or writing to outputs and at the very basic level something like this water sensor is an analog sensor and I can use something called an analog read function and I tell it which pin to read from and I can read a value so it's very basic very simple that's how I can read and interact with a sensor some things like this DHT11 are a little more complicated a little more complex not terribly but oftentimes you will find as you can see on line 146 that there are open source libraries out there that will help you read from these types of sensors so if you see on 146 I'm using the DHT library and I use the call the read11 function I tell it what pin that sensor is connected to and then on the next line you can see that I have an object returned from that function or from the library that allows me to check the current temperature and the current humidity also I have a helper function to convert that from Celsius to Fahrenheit because the initial sensor reading comes in Celsius and we can go further and look at other examples here the probe thermometer for example has its own library as I said the moisture sensor that I just showed you has just uses the basic Arduino analog read function and so on and so forth I create strings and that's used to display on my little OLED display here but at the end of that what I'm also doing is creating a JSON document and I'm setting all those values into that JSON document so the current relay state whether it's on or off the air temperature, the soil temperature all these things I'm setting into this JSON object I'm serializing it and then finally down here on 225 I'm publishing that up to that MQTT topic so I've got this JSON object every 10 seconds, 60 seconds however often in this case one second I'm publishing that up to the MQTT topic so it's just this nice JSON string it's going out over the air and everything is good now let's talk about before I go to the the actual processing and consuming of that topic a little bit about the database schema so there are options of course how I could persist this data into the database and I wanted to persist it because I wanted to be able to run reports and queries on it and aggregations and things like that so it was important to persist the data into a database for me I could have created there's a couple options I could have created separate tables for every sensor the outlet sensor is a boolean value it's on or off, it's true or false essentially the probe thermometer it has a float type reading gives me back a decimal type data the light gives me an integer so I could have created a separate table you see what I'm saying for each of these and had a custom column for all those different types that's not very flexible it's very rigid I thought maybe a better option might be to just store this data as JSON in the database that gave me a little more flexibility because if I had more sensors or if I change one of these sensors maybe I decided I don't need a float anymore it keeps it flexible it allows me to have a little bit of flexibility so I created this table and let me actually show you that real quick it's just the schema of it did we time out oh there we go so yeah it was wasn't it maybe I spilled the water on my machine alright so I have an ID column it's an auto number just gives me a primary key for each reading then I'm storing the reading I have a column for the reading as a club character large object and that's what I'm using to store the JSON string in the database and then I just have a basic created on timestamps so I know so I can order and sort and things like that there is a constraint on the reading column to ensure that the reading is valid JSON so this allows me to make sure that I'm not persisting like a broken JSON string and maybe it didn't get read fully I want to make sure that it's actual JSON so I have that constraint on it so if we query that table really quickly we can see that very simply like I said the JSON is stored in that reading column the nice thing about the Oracle database is that it treats that JSON as basically a first class citizen in the database so I can actually query directly into that into that column and actually pull those values out individually this allows me to do those nice aggregations so if I wanted to pull out those and I wanted to pull out the air temp is it air temp or air temperature air temp okay and I can do whatever I need to I can order by so it treats it all like a first class citizen in my table so that I can sort it, aggregate do all those fun things so I also have some materialized views we won't look at those right now but essentially this allowed me the flexibility to store that JSON into the database and work with it further let's talk now about the actual micronaut application that does the persistence, does the visualization, all that fun stuff so is anybody familiar with micronaut or java? are we yeah, yeah okay awesome so micronaut is my favorite framework to use in the java world we've kind of taken this shift in the last few years as you're probably familiar with from doing things at runtime to doing things at compile time so we're seeing frameworks like quarkis and micronaut that are coming up with these very intelligent very smart ways of pre-compiling our code inferring things based on annotations and making our runtime performance much better so in the past a lot of things, a lot of the frameworks and libraries that we relied upon did a lot of that stuff at runtime and it stored all that stuff using reflection and proxies and things like that stored all that stuff in memory which is the old joke memory is cheap right but we're moving into this cloud age where memory is cheap but if we lower that memory consumption our costs can go down and if we want to use things like serverless technologies we need to be more performant at runtime we can't have cold starts that take 5 seconds, 10 seconds that's just a deal breaker in the Java world and it's why some other languages have kind of gained so much traction in that serverless world because they have that very low startup time cold startups are immediate with node or go or some of these other languages so Java had to kind of catch up in that world and that's why I think you're seeing a lot of these types of frameworks that use this compile time style of basically to make up for that so I want to show you real quickly if you're not familiar with Mike or not I want to show you how quickly I can get up and running because to me someone who's been around the JVM for almost 20 years but really not worked directly in Java in other words I've been in JVM style languages one of the biggest things to me biggest barriers to entry in the Java world was set up in configuration how do you get a web server up and running how do you get Netty up and running or Jetty or any of these types of things so the reason I really one of the reasons I really like Mike or not is it lowers that barrier to entry it makes it really easy to get an app up and running so as an example I have the Mike or not CLI installed and if I call create app and I tell it the build system I want to use in this case Gradle you can also choose Maven the JDK I want to use the language I want to use because it supports Kotlin and Groovy as well so in this case I want to use Java and then tell it the name of my application and in this case I'm going to also do a copy for the Gradle wrapper because otherwise we'd be waiting a while for that to download here so if I create that I've got an application created so if I move into that look we see all those files they're there for me I didn't have to create them I didn't have to create a build script in Gradle I didn't have to create the structure of my application I didn't have to create any of the manifests or any of the other files that are necessary to get this up and running it's just all done for me and if I wanted to create for example a controller we just call MNCreateController and I've got a controller so let's take a look really quickly at that controller and this is the code I get out of the box when I scaffold out a controller so it's a public class annotated with atController just tell it the path that you want it to be available on and then identify your routes within that as different methods so in this case we have a single method just available at hello slash there returns a string example response so to run that at this point using the Gradle wrapper I hit Gradle W run and within about one second as you can see there I've got my server up and running and ready to respond to requests so as you can see there you have your example response so within two minutes I've got an entire project scaffolded it out ready to go I don't have to create the main method I don't have to it's just ready to go it just lowers that barrier to entry for me I can focus on the actual code that makes my application what it is so to me that's something that's pretty impressive and one of the other really awesome things about Micronaut is it has a very extensive open source plugin ecosystem around it so they call them features in Micronaut but if you've used something like spring or grails or something like this you're probably familiar with plugins and these are either community contributed or developed by the core team and they're essentially just little bits that we can add into our application to make other things easier one of the really cool plugins features available in Micronaut is something called Micronaut data and this makes persistence of basically basic CRUD operations it makes them very easy to use and I want to show you how this application uses Micronaut data so let me jump into presentation mode here and so the first thing we have to do when we use Micronaut data well we have to make sure that we have the dependencies that we need and we can get those by passing them into the MNCreateApp command on the command line as just named features at the command line or we can go to launch.micronaut.io which is a nice web based GUI that lets you drop down menu pick which features you want to add your JDK all that stuff so couple different ways we can get that and we can download that and run it so the first thing we need to do if we want to add persistence with Micronaut data is create an entity and an entity in this case is just a basic pojo right it's just a class with some properties in this case all the properties map to my database columns the other nice thing about Micronaut data like many similar types of libraries it actually maps things like ugly underscore cased database columns to nice to look at camel case columns in our Java code I'm not sure why we ever determined that underscore was the best way to store our database column names but it is what it is typically we go along with that but it's smart enough to interpret those types of things we just tell it the table name and if I were to name this green thumb readings like this it would be smart enough to interpret that itself but just to illustrate that there is a way to map a class name to a different table name I show you that we can do add this entity name table name attribute to the class to specify that and I've also annotated it with at entity and these are built in classes actually in this case these are JPA annotations that it identifies and knows what they mean so we've got a constructor we've got getters and setters just your typical type of POJO class that we've seen probably a thousand times before if we've worked with Java now the next thing we need to do is create what's called a reading repository or a repository and this interface as you see here size okay on that yeah okay so this interface as you see here extends the pageable repository interface and the pageable repository interface class is a built-in class in micronaut so we just extend that we tell it our entity type and the type that is used for the id for that table and if I were to have nothing else if this line wasn't even here in line 12 and I compiled this and I ran it at runtime I would have create, read, update, delete get all those methods implemented for me all done don't have to write a single line of code beyond this they're all already inferred by that compile time introspection that looks at the metadata it looks at the table all that kind of fun stuff is done for me I don't have to write another single line of code now in this case I wanted to have an async method to be able to save these items asynchronously so the only thing I need to do is provide a signature that ends in the word async and returns an async compatible value in this case a completable future and then what it's trying to save which is the reading class and again this is implemented for me all done at compile time and ready to go in this case since I've implemented pageable repository I've also get support for pagination so all my list methods I can pass it a page item which contains the start and the end and it gives me built in pagination out of the box there are other types of repositories that you can implement check the documentation on that and the only other thing I need to do is annotate that with at repository now this is the JPA compatible micronaut data which is hibernate if you think of JPA there's also a JDBC micronaut data flavor if you will that will not use any kind of hibernate type thing it'll just write out raw sequel for you that will be executed at run time against the database so depending on your needs and what you want to do there are options to go that way now that's nice that's helpful crud is boring and boilerplate so I don't personally like to write boring inserts and updates and get and lists but it's a little rigid, not rigid limiting so it's just basic crud what if we wanted to do more than basic crud what if I wanted to run my reporting queries against the database well in that case we can implement an abstract class in this case what I call the abstract repeating repository so I have an abstract class called abstract reading repository that implements pageable repository and in this case in my constructor I can inject an entity manager and that's a java persistence entity manager and I'll get an entity manager injected into this which allows me to construct my sequel queries and then create and execute native queries against that data source so it's nice to get that out of the box easy crud but to also have that flexibility to run more advanced code on top of that is to me a really awesome feature so essentially that is persistence in my crud I mean it's a little I've kind of skimmed over a lot of it but honestly there's really not much more to it so let's look now at the consumer class called green thumb consumer and one of the other awesome features in my cronaut is an MQTT plugin so I can add this dependency on the MQTT plugin and out of the box I'm able to add things like this MQTT subscriber to my application annotated with MQTT subscriber and the only other thing I need to do well I take that back of course there's configuration so if you look at the my YAML file you do have a little bit of configuration which you would expect you'd need to tell the client are the username the password the URL things like that but other than that the only thing I need to do is tell it annotate a receive method within that class that tells it what topic to consume and every time a new message is received from that MQTT topic this method will be invoked so what do I do with that well I have a single argument and that is a what I call data and that is a map with the keys being a string and the value being an object the nice thing one of the other awesome things about my cronaut is that as I told you I was publishing a JSON string to that MQTT topic my cronaut is intelligent enough to deserialize that into an actual object just by telling it the signature in the receive method so rather than receive a string and manually deserializing it I can just tell my cronaut hey make sure that when you get this it's a map with keys of string and values of object and when that message comes in that's what I get and object because obviously like I said there could be booleans there could be floats there could be various different values within that value of that JSON object so the next thing I do is I just create a reading from that data and I have a constructor that just accepts that map and calls all my getters and setters and gives me a reading object down here on line 55 I've injected the reading repository which is what we just looked at that I've got a third repository I've injected that into my consumer and so I can just call that save async method pass it the reading and my reading is persisted based on the soil moisture level one of the other things I wanted to add because I like I said I did not automate the watering but I did want to keep an eye on it so one of the things I implemented was push notification to my mobile device so that if the level dropped below a certain threshold I would get notifications and if we look over here nope I didn't get any when it was running I don't think it was running long enough to send it but essentially I use the third party system called push over which is really cool if you're not familiar with it I do suggest you check it out it's an app that you install on your smart phone pushover.net and it's a one time purchase $5 and you can use it for push notifications on your device you get a user id that is specific to your device and through their apis or through rest calls you can send push notifications to your device you don't have to worry about coding your own android app or ios app or desktop app for push notifications you don't have to worry about coding your own android app or iOS app for push notifications you can just use their apis which I think is kind of nice so I use this pushover client in this case if my water moisture level drops below a certain threshold and if it's been and I don't want to send it every single time I get a reading so I set an interval and basically every 20 minutes make sure that I'm sending this push notification and I use this pushover client push message method to and I pass it the api key my user key and then the message itself that I want to send to the push notification so let's take another look or let's take a look at the pushover client that I'm using so another awesome feature of micronaut is what they call declarative HTTP clients and a declarative HTTP client in this case is an interface that's annotated with that client and the at client annotation accepts the root URL to use for that client and it just has method signatures for each method that you want to map to that HTTP endpoint so in this case the endpoint for the pushover rest api is slash one slash messages.json it produces application form URL encoded and it consumes JSON so I have this push message method and at compile time micronaut takes care of all the nasty plumbing that's involved with making HTTP requests and at runtime I have this nice client ready to go so I call this push message method it maps all of these different parameters that I've defined in the signature to URL parameters and it constructs the request sends the request and allows me to do in this case async calls since I'm returning a flowable to that endpoint and if we come back to the consumer you can see that I'm calling the blocking first method so I am using blocking which kind of defeats the purpose of making an async request but essentially all that hard work of all that plumbing involved in making HTTP calls in Java is done for me I don't have to worry about it and it's all good to go finally the last thing I do here is I have this broadcaster and I call the broadcast async method and I pass it that data which is that JSON object that comes in now what is the broadcaster the broadcaster is another awesome feature micronaut which is support for web sockets so it's a instance of web socket broadcaster and if we look at web socket broadcaster oops that's not what I wanted to do web socket so if we look at the green thumb web socket class that I have in this application it's annotated with at server web socket and the URL endpoint that I want to use for that web socket so we're all probably familiar with web sockets right it's just a way for our javascript applications to kind of receive data pushed to them or send data back real time communication real time sockets inside the browser well in this case the only thing I need to do in micronaut is create this class and then annotate certain methods with various annotations and then do something within those methods right so on open when the web socket connection is open on a client this method is called and it just broadcasts a message that when it receives a message into the server it will broadcast that message so on close so on and so forth so it's a really easy way to get web socket communication in your java application just with some annotations and some specifically named methods and properly annotated so you have web socket communication so if we go back to that consumer like I said I'm pushing that data out to the connected clients via that broadcaster so essentially that's it I could show you the controller and views but there's not much to them I just two endpoints I have an index endpoint that shows me the the charts and graphs and I have a reports page that I can use to display those reports I'll show you that real quick because I didn't show you that so if we look at the reports page it's just some basic table based data what you'd expect to see in a reports page and the index page has that web socket consumer and that allows me to update those real time charts so I push those readings out to the client I saved the last 25 of them I think if I look at my charts it's the last 25 readings into an array and I update my charts in real time so jump back to the slides really really quickly because I'm running out of time here and jump down to the end so what are the results that's really the important thing how did I do on the results so as you can see here I was fairly pretty good on most of my results the ones that I missed I missed barely but it allowed me to really kind of control this process and it was a really fun project it allowed me to learn some new things it allowed me to have some blog content to blog and put out there on my blog allowed me to do this presentation but all in all it was a really fun project and as you can see here the seedlings did come up they did grow my peppers did come up they did bloom as you can see here and I did make some hot sauce a couple weeks ago from this like the idiot I am so you'll have to take my word on it that it came out really well and yeah that's it so I have as I said quite a long series of blog posts if you're interested down at the bottom of the screen there is a couple repos if you want to take a look at any of the code it's all available up on on github and any questions cool here's my blog, here's my socials that hook up be friends I'll be your best friend thank you