{"id":290,"date":"2023-05-08T18:41:25","date_gmt":"2023-05-08T18:41:25","guid":{"rendered":"https:\/\/dwich.de\/?p=290"},"modified":"2023-05-08T18:41:28","modified_gmt":"2023-05-08T18:41:28","slug":"shelly-monitor-part-1","status":"publish","type":"post","link":"https:\/\/dwich.de\/?p=290","title":{"rendered":"Shelly Monitor (Part 1)"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><p>Why I love developing with Spring Boot.\nIn this first part I would like to show how easy and fast an executable \/ useful app can be created.<\/p>\n<p>I use Spring Boot because the best source code is the one I don&#8217;t have to write. (and more importantly in my opinion, I or the developer who comes after me won&#8217;t need to read this source code in maybe a few months)<\/p>\n<p><a href=\"https:\/\/github.com\/dirk-w\/shelly-monitor\">Sources on github<\/a><\/p>\n<h2>Motivation<\/h2>\n<p>I have a photovoltaic (PV) system on the roof, which is connected via a Shelly switch actuator to measure the electricity generated.\nUnfortunately, this failed last winter and I only noticed it quite late.\nLuckily, the Shelly has a rest interface that you can use to query the status.\nSo I came up with the idea of writing a small monitoring program.<\/p>\n<p>Of course you could also do such a job with CheckMK or Zabbix, but a small program in Java (with Spring Boot) should also be written quickly.<\/p>\n<h2>Requirements<\/h2>\n<p>So what do I need (the requirements)<\/p>\n<ul>\n<li>Job should be executed regularly<\/li>\n<li>Rest interface must be queried<\/li>\n<li>If the status is not OK, an email should be sent<\/li>\n<li>of course, most of the parameters should be configurable<\/li>\n<\/ul>\n<h2>Create Project<\/h2>\n<p>Start with <a href=\"https:\/\/start.spring.io\/\">Spring Initializr<\/a>\nFor scheduling tasks we don&#8217;t need any dependencys\nTo consume the webservice we need Spring Web as a dependency\nFor sending E-Mails we need Java Mail<\/p>\n<\/div>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"310\" src=\"https:\/\/i0.wp.com\/dwich.de\/wp-content\/uploads\/2023\/05\/Bildschirmfoto-vom-2023-04-06-18-20-13-1024x496.png?resize=640%2C310&#038;ssl=1\" alt=\"\" class=\"wp-image-291\" srcset=\"https:\/\/i0.wp.com\/dwich.de\/wp-content\/uploads\/2023\/05\/Bildschirmfoto-vom-2023-04-06-18-20-13.png?resize=1024%2C496&amp;ssl=1 1024w, https:\/\/i0.wp.com\/dwich.de\/wp-content\/uploads\/2023\/05\/Bildschirmfoto-vom-2023-04-06-18-20-13.png?resize=300%2C145&amp;ssl=1 300w, https:\/\/i0.wp.com\/dwich.de\/wp-content\/uploads\/2023\/05\/Bildschirmfoto-vom-2023-04-06-18-20-13.png?resize=768%2C372&amp;ssl=1 768w, https:\/\/i0.wp.com\/dwich.de\/wp-content\/uploads\/2023\/05\/Bildschirmfoto-vom-2023-04-06-18-20-13.png?resize=1170%2C566&amp;ssl=1 1170w, https:\/\/i0.wp.com\/dwich.de\/wp-content\/uploads\/2023\/05\/Bildschirmfoto-vom-2023-04-06-18-20-13.png?w=1533&amp;ssl=1 1533w, https:\/\/i0.wp.com\/dwich.de\/wp-content\/uploads\/2023\/05\/Bildschirmfoto-vom-2023-04-06-18-20-13.png?w=1280 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-jetpack-markdown\"><p>after downloading the zip file and extracting it we could start.<\/p>\n<h3>other dependencys<\/h3>\n<p>The dependency awaitility is needed for testing tasks (must be done in second part)\nI love to use lombok for logging etc.<\/p>\n<h3>Technical requirements<\/h3>\n<p>To run the examples you need only a handfull of tools<\/p>\n<ul>\n<li>Maven 3.9.1 use <a href=\"https:\/\/sdkman.io\/\">SDKMAN<\/a><\/li>\n<li>Java 17 Development Kit (JDK 17) use <a href=\"https:\/\/sdkman.io\/\">SDKMAN<\/a><\/li>\n<\/ul>\n<p>maybe I write an other blog about SDKMAN.<\/p>\n<h3>the shelly resource<\/h3>\n<p>I want to consume a rest api from shelly.\nThe api is reachable under (changed IP adress)\nhttp:\/\/127.0.0.1\/relay\/0\nthis is the json delivered by this endpoint<\/p>\n<pre><code>{\n\t&quot;ison&quot;: false,\n\t&quot;has_timer&quot;: false,\n\t&quot;timer_started&quot;: 0,\n\t&quot;timer_duration&quot;: 0,\n\t&quot;timer_remaining&quot;: 0,\n\t&quot;overpower&quot;: false,\n\t&quot;overtemperature&quot;: false,\n\t&quot;is_valid&quot;: true,\n\t&quot;source&quot;: &quot;http&quot;\n}\n<\/code><\/pre>\n<h2>Implementation of the requirements<\/h2>\n<p>First I create the rough structure in the project by creating the following packages:<\/p>\n<ul>\n<li>email<\/li>\n<li>obj<\/li>\n<li>props<\/li>\n<li>scheduler<\/li>\n<li>service<\/li>\n<\/ul>\n<p>an empty application.properties file already exists (located under src\/main\/resources)<\/p>\n<h3>The scheduler<\/h3>\n<p>The package scheduler contains the class ScheduledTask.<\/p>\n<p>Not much exciting happens here, the class must be marked with <code>@Component<\/code> so that it appears in the application context.\nThen a service is inserted via constructor injection. This service will do the work \ud83d\ude42 see below.<\/p>\n<p>Only the methode annotation is interesting. This states that the method is called in the interval of the cron expression.\nThe cron expression itself comes from the configuration (application.properties) and there the key: eu.dwich.scheduler.cron<\/p>\n<h3>The configuration<\/h3>\n<p>In addition to the cron expression, the application.properties also contains the URL to the Shelly interface, parameters for notification and the configuration for sending emails.\nSince I need some of this values in the service, I created the ConfigProps class under props.\nThis has two annotations, so the class is initialized with values from the application.properties.\nThe attributes are reffrenced over <code>@Value(&quot;key from properties file&quot;)<\/code>\nFrom the application context I can then injected the object into the service class (constructor injection).<\/p>\n<p>Spring Magic, I don&#8217;t have to worry about anything else (open file, read properties etc.)<\/p>\n<h3>Send e-mail<\/h3>\n<p>EmailService, realy simpel.\nI use the Spring class JavaMailSender (initialized with application.properties) to send a SimpleMailMessage, which was initialized by the methode parameters.\nThat&#8217;s all, nothing more to do for sending E-Mails.<\/p>\n<h3>Query the rest of the interface<\/h3>\n<p>The CheckShellyService class is a little more complex (but not really much)\nAll Java Beans that I need are already initialized in the application context. From there I can have them injected using constructor injection.<\/p>\n<p>Then there is only the method checkShellyIsSwitched().\nNothing exciting here either except for line 30.<\/p>\n<p>Here you find Spring magic again.\nThe Spring restTemplate.getForObject method calls the Shelly URL, which returns JSON.\nThis JSON is automatically parsed into a Java Record object. It can be found under obj\/ShellyValues.\nHere you only have to make sure that the attribute names and data types match.\nSo for example <code>boolean ison<\/code> corresponds to the JSON attribute <code>&quot;ison&quot;: false,<\/code> or <code>long timer_started<\/code> corresponds to the JSON attribute <code>&quot;timer_started&quot;: 0,<\/code>\nObject structures can also be mapped, please see the Spring documentation for more details.<\/p>\n<h2>Conclusion<\/h2>\n<p>I was able to successfully implement the project with just under 1.5 hours of development time.\nI will now start this on my NAS as a test and see how it runs.<\/p>\n<h2>More thoughts<\/h2>\n<p>Next, I could pack the finished program into a docker container, whereby I have to put the configuration outside.\nI would tackle this in the next part and publish it here.\nThen there are Tests missing, thats also part of the next blog.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[5,16],"tags":[11],"class_list":["post-290","post","type-post","status-publish","format-standard","hentry","category-java","category-spring-boot","tag-spring-boot","two-columns"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/dwich.de\/index.php?rest_route=\/wp\/v2\/posts\/290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dwich.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dwich.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dwich.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dwich.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=290"}],"version-history":[{"count":1,"href":"https:\/\/dwich.de\/index.php?rest_route=\/wp\/v2\/posts\/290\/revisions"}],"predecessor-version":[{"id":292,"href":"https:\/\/dwich.de\/index.php?rest_route=\/wp\/v2\/posts\/290\/revisions\/292"}],"wp:attachment":[{"href":"https:\/\/dwich.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=290"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dwich.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=290"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dwich.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}