Shelly Monitor (Part 1)

Why I love developing with Spring Boot. In this first part I would like to show how easy and fast an executable / useful app can be created.

I use Spring Boot because the best source code is the one I don’t have to write. (and more importantly in my opinion, I or the developer who comes after me won’t need to read this source code in maybe a few months)

Sources on github

Motivation

I have a photovoltaic (PV) system on the roof, which is connected via a Shelly switch actuator to measure the electricity generated. Unfortunately, this failed last winter and I only noticed it quite late. Luckily, the Shelly has a rest interface that you can use to query the status. So I came up with the idea of writing a small monitoring program.

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.

Requirements

So what do I need (the requirements)

  • Job should be executed regularly
  • Rest interface must be queried
  • If the status is not OK, an email should be sent
  • of course, most of the parameters should be configurable

Create Project

Start with Spring Initializr For scheduling tasks we don’t need any dependencys To consume the webservice we need Spring Web as a dependency For sending E-Mails we need Java Mail

after downloading the zip file and extracting it we could start.

other dependencys

The dependency awaitility is needed for testing tasks (must be done in second part) I love to use lombok for logging etc.

Technical requirements

To run the examples you need only a handfull of tools

  • Maven 3.9.1 use SDKMAN
  • Java 17 Development Kit (JDK 17) use SDKMAN

maybe I write an other blog about SDKMAN.

the shelly resource

I want to consume a rest api from shelly. The api is reachable under (changed IP adress) http://127.0.0.1/relay/0 this is the json delivered by this endpoint

{
	"ison": false,
	"has_timer": false,
	"timer_started": 0,
	"timer_duration": 0,
	"timer_remaining": 0,
	"overpower": false,
	"overtemperature": false,
	"is_valid": true,
	"source": "http"
}

Implementation of the requirements

First I create the rough structure in the project by creating the following packages:

  • email
  • obj
  • props
  • scheduler
  • service

an empty application.properties file already exists (located under src/main/resources)

The scheduler

The package scheduler contains the class ScheduledTask.

Not much exciting happens here, the class must be marked with @Component so that it appears in the application context. Then a service is inserted via constructor injection. This service will do the work 🙂 see below.

Only the methode annotation is interesting. This states that the method is called in the interval of the cron expression. The cron expression itself comes from the configuration (application.properties) and there the key: eu.dwich.scheduler.cron

The configuration

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. Since I need some of this values in the service, I created the ConfigProps class under props. This has two annotations, so the class is initialized with values from the application.properties. The attributes are reffrenced over @Value("key from properties file") From the application context I can then injected the object into the service class (constructor injection).

Spring Magic, I don’t have to worry about anything else (open file, read properties etc.)

Send e-mail

EmailService, realy simpel. I use the Spring class JavaMailSender (initialized with application.properties) to send a SimpleMailMessage, which was initialized by the methode parameters. That’s all, nothing more to do for sending E-Mails.

Query the rest of the interface

The CheckShellyService class is a little more complex (but not really much) All Java Beans that I need are already initialized in the application context. From there I can have them injected using constructor injection.

Then there is only the method checkShellyIsSwitched(). Nothing exciting here either except for line 30.

Here you find Spring magic again. The Spring restTemplate.getForObject method calls the Shelly URL, which returns JSON. This JSON is automatically parsed into a Java Record object. It can be found under obj/ShellyValues. Here you only have to make sure that the attribute names and data types match. So for example boolean ison corresponds to the JSON attribute "ison": false, or long timer_started corresponds to the JSON attribute "timer_started": 0, Object structures can also be mapped, please see the Spring documentation for more details.

Conclusion

I was able to successfully implement the project with just under 1.5 hours of development time. I will now start this on my NAS as a test and see how it runs.

More thoughts

Next, I could pack the finished program into a docker container, whereby I have to put the configuration outside. I would tackle this in the next part and publish it here. Then there are Tests missing, thats also part of the next blog.

WordPress Cookie Plugin von Real Cookie Banner