Take screenshot of sitemap charts (grafana) and attach to email

Hardware: RPi3 B+
openHAB version: openhab2.5.12 (v1.6.1b)

FYI: I have some experience with Java and C++, but I do not have much experience with linux, shell scripting, or permission issues, etc. So please excuse my ignorance. I have spent a few days trying to learn, understand and figure it out, but I haven’t been successful. I have no other choice but to ask the community for help. This might be a long post, since I have tried to explain as much as I think might be relevant. Hopefully a kind soul will see this and act as a mentor.
This is probably my first topic ever, so if I make any mistake or do things incorrectly, please advise how I can do it correctly.

I am trying to follow this post:

Some things I would like to do differently:

  • instead of using crontab, I would like to use a rule which will trigger once a day, take a screenshot of my sitemap and save in /etc/openhab2/html folder
  • then another rule will send an email with that png as an attachment

How exactly does executeCommandLine work? I am still not sure that I understand. From the docs, I see it can execute a .sh file, like we would from the terminal ./file.sh, but it does not run like any command from a linux terminal? Almost all of the examples that I have seen in the community forums execute a .sh file using executeCommandLine.

IF thats the case, then I can write a .sh file (as of now I do not know exactly how to do this) which will contain the commands to take screenshot and save it as a png (contents of Rule 1 below), put this file in the scripts directory of openhab (/etc/openhab2/scripts), then execute this file using executeCommandLine in a rule.

Before putting anything in a rule, I tried to run the command from the terminal (putty) and see if it works and saves a screenshot in the directory provided:

sudo xvfb-run --server-args="-screen 0, 640×480x24" cutycapt --url= --out=/etc/openhab2/html/Grafana_Temp.png

This returns:
[1] 17496
-bash: --out=/etc/openhab2/html/Grafana_Temp.png: No such file or directory

I have no idea what that means, because that directory (html folder) definitely exists. Ideally, my two rules would be as follows:

rule "Rule 1: take screenshot and save grafana chart"
    Time Cron "0 0 12 ? * * *"   //At 12:00:00pm every day
    logInfo("Notification", "screenshotGrafana RULE triggered")
    executeCommandLine("xvfb-run --server-args="-screen 0, 640×480x24" cutycapt --url=http://<ip_address>:8080/basicui/app?w=0300&sitemap=FR2 --out=/etc/openhab2/html/Grafana_Temp.png")

Inside the executeCommandLine(""), should I use \ for the quotation marks around --server-args="-screen 0, 640×480x24" ?
Like this:

executeCommandLine("xvfb-run --server-args=\"-screen 0, 640×480x24\" cutycapt --url= --out=/etc/openhab2/html/Grafana_Temp.png")
rule "Rule 2: send grafana screenshot as email attachment"
    Time Cron "0 0 13 ? * * *"   //At 13:00:00pm every day
    logInfo("Notification", "Sending email with screenshotGrafana - RULE triggered")

//for now just one screenshot, later I'll add another file when I have this working
    val List<String> emailAttachments = newArrayList(

    val mailActions = getActions("mail","mail:smtp:sample")  //
    mailActions.sendMail("myname@myemail.com", "Email-Notification", emailAttachments)

Any suggestions, advice, tutorials would be highly appreciated. Thank you!

It executes a single command. Hence the name. But it doesn’t not have access to a shell. The shell provides features like I/O redirection like pipes | and tee and > and the like. One of the powers of Unix type environments is the ability to take the output from one command and use it as the input to another command.

cat /var/log/syslog | grep foo | grep bar | less

That will print out the contents of /var/log/syslog and pass it to grep which will output only those lines containing “foo” and pass those to another grep which will extract those lines containing “bar” and finally pass those lines to less which will let you view the results.

In short that command means “give me all the lines in /var/log/syslog” that contain both “foo” and “bar”".

You can’t do that in executeCommandLine by itself. So most people who need to accomplish something like that will put that into a script. The first line of a script includes a #!<shell> where <shell> is something like /bin/bash. That tells the OS you want to execute everything that follows using /bin/bash. Since it’ll be running in a shell now you have access to all the shell features.

Shells also provide other useful things like environment variables (e.g. $PATH which tells it what folders to look in when you type a command), the ability to execute more than one command in sequence without piping the results, etc.

There are dozens of tutorials out there and a full tutorial on that is beyond the scope of this forum. At a high level:

  • first line will be #!/bin/bash
  • type in the commands that the script should performs similar to what you would type on the terminal prompt
  • save the file and set the permissions to allow execution

This is one reason why people have such a hard time with executeCommandLine and the Exec program. As with any other technology OH interacts with, in order to be successful you must have a basic understanding the technology you are using. In this case the technology you are interacting with is the Linux operating system.

The gotcha here is everything in Linux operates as an assigned user. There is not a process that is running nor a file that isn’t owned by some explicitly defined user. And each user has their own environment. When you log in and execute that command on the command line you are executing it as your login user (openhabian if you are using openHABian, pi if stock Raspbian, etc). But openHAB runs under the openhab user. So your experiment doesn’t show you anything because it doesn’t show how the command will run as the openhab user.

Hint, it probably won’t work because the openhab user doesn’t have permission to run sudo.

The answer to that will be in the docs for xvfb. That’s outside the scope of this forum and I know nothing of this specific tool.

However, note that if you ran the command with sudo that means "run everything after as the user root" which means all the files created will be owned by root. Other users may not have permission to read/write to that file later on.

You do not use sudo in your rule.

NOTE: the arguments to executeCommandLine changed in OH 3.

In OH 2 you should replace the spaces that denote the separate arguments with @@.


Yes, that prevents OH from interpreting it as a closing quote.


Thank you Rich! I have a much better understanding now on how executeCommandLine is supposed to work. I’ll put the contents of Rule 1 in a .sh file and store it in /etc/openhab2/scripts folder.

Could you please guide me on how I can set permissions to allow execution after saving the .sh file?

Its openhabian in my case. I think the first thing for me to try right now is put Rule 1 in a .sh file and run using executeCommandLine. That seems to be the right way forward.

On the terminal, I ran the command without “sudo”, just like I have it in the rule:

xvfb-run --server-args="-screen 0, 640×480x24" cutycapt --url=http://<ip_address>:8080/basicui/app?w=0300&sitemap=FR2 --out=/etc/openhab2/html/Grafana_Temp.png

This returns:

[4] 20373
-bash: ip_address: No such file or directory
-bash: --out=/etc/openhab2/html/Grafana_Temp.png: No such file or directory
[4]   Exit 1                  xvfb-run --server-args="-screen 0, 640×480x24" cutycapt --url=http:// < ip_address > :8080/basicui/app?w=0300

I honestly have no idea what these mean.

Finally someone explains why I see those weird @@ everywhere on the examples I found!

I’ll continue and try the things that I have learned from your post. I’ll come back with my new findings. I hope I am not being a nuisance. Once again, thank you Rich!

Rich’s post is awesome and could be considered required reading for anyone new to pi/linux usage. If your usecase is really just a snapshot of the grafana chart however, then there is a much more direct solution to your larger question.

The mail actions that accept local file names as attachments will also accept web addresses as attachments. Your grafana instance should provide a direct url to a rendered version of any panel on a dashboard (maybe you have already even found this depending on how you added the chart to your sitemap).

From the panel dropdown on the grafana dashboard select share and on the share dialog click the direct link rendered image button. This will open up a new tab with the url that returns a png of that panel from the renderer (sometimes takes a few seconds depending on the panel). If the image is rendered at full screen resolution in that link you can replace the &fullscreen with &width=640&height=640 or whatever dimensions you want.

Put that grafana url directly into your mail action and you can skip all the external scripting altogether and just run a single rule.


Here’s the thing. Remember I said that to be successful integrating any technology with OH you need to be familiar with that technology? Well this is Linux 101 stuff.If you don’t know this, or more importantly you don’t know how to search Google to find the answer to this, you really need to get a book or go through an online Linux class or tutorial. Generic Linux support us generally outside the scope of this forum. A simple search for “change linux file permissions” will reveal hundreds of tutorials posted to the web here and there. But you’re going to need more basic knowledge than that so I recommend a more thorough Beginning with Linux tutorial.

You don’t have to know much about Linux to use openHABian. But if you want to use executeCommandLine or the Exec binding you must have basic knowledge of how to work in Linux.

I don’t know anything about xvfb either so I don’t know either. You’ll have to get that answer from the xvfb docs, website, forum, etc. That’s not an openHAB nor an openHABian question. I’d guess that you have formatted the --out argument incorrectly or put it in the wrong order or something like that.

From the executeCommandLine docs: Actions | openHAB

Simple arguments that contain no spaces can be separated with spaces, for example executeCommandLine("touch file.txt"). When one or more arguments contain spaces, use @@ instead of a space as the argument separator. For example the bash command touch -t 01010000 "some file with space.txt" will have to be written as touch@@-t@@01010000@@some file with space.txt.

With openHAB more so than almost any other software or platform, going back and reviewing the docs again is not optional. I’ve been using openHAB for the better part of a decade now and even I look stuff up in the docs at least once a week.


did you try to use directory /tmp instead of /etc/openhab2/html/ ?

I would suggest you try the following ( remove the server arg, at least for a trial and put the url in between double quotes ) :

xvfb-run  cutycapt --url="" --out=/etc/openhab2/html/Grafana_Temp.png

Thank you so much for your response. I did not try a different directory. Since I have mapped openHAB-conf as a network drive, I wanted to save it in html directory so that I could open and see it right away for verification.

On a slightly different note, I have started a fresh install on a new raspberry:
Hardware: RPi3 B+
openHAB version: openhab2.5.12 (v1.6.1b)

Installed influxdb, but I am getting errors when installing grafana, even though I followed the exact same steps just last week on a differenet RPi:

I am following this link to install grafana on my raspberry pi:

I installed grafana on another raspberry pi successfully just last week. Today on a new raspberry pi, unfortunately, I am getting errors:

sudo apt-get install -y grafana
Reading package lists… Done
Building dependency tree
Reading state information… Done
Package grafana is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package ‘grafana’ has no installation candidate

I did not find any solution online. I am hoping someone can shed light on this issue. I am unable to display graphs on sitemap and try your suggestions until then. Thank you again for your help!

Try it to make sure that the problem is not cause by any other cause.
Once it works you can investigate why it works with /tmp and not with the other folder.
In case it also does not work with /tmp it is not a problem of the directory itself.

With regard to grafana install problem either you do not have created an entry in /etc/apt/sources.list.d (
/etc/apt/sources.list.d/grafana.list ) or you forget to run sudo apt-get update afterwards.

Yes I do have entry in /etc/apt. I think there’s 4 instances because I tried to install it multiple times

openhabian@openhabMK:~ $ cat /etc/apt/sources.list.d/grafana.list
deb https://packages.grafana.com/oss/deb stable main
deb https://packages.grafana.com/oss/deb stable main
deb https://packages.grafana.com/oss/deb stable main
deb https://packages.grafana.com/oss/deb stable main

Actually I did run apt-get updat afterwards. I ran it again and jus now I noticed this error:

openhabian@openhabMK:~ $ sudo apt-get update
[sudo] password for openhabian:
Get:1 http://davesteele.github.io/comitup/repo comitup InRelease [3,936 B]
Hit:2 http://archive.raspberrypi.org/debian buster InRelease
Hit:3 https://repos.influxdata.com/debian jessie InRelease
Hit:4 https://deb.nodesource.com/node_12.x buster InRelease
Get:5 http://raspbian.raspberrypi.org/raspbian buster InRelease [15.0 kB]
Get:6 https://packages.grafana.com/oss/deb stable InRelease [12.1 kB]
Hit:7 https://openhab.jfrog.io/artifactory/openhab-linuxpkg stable InRelease
Get:8 https://packages.grafana.com/oss/deb stable/main armhf Packages [27.5 kB]
Err:8 https://packages.grafana.com/oss/deb stable/main armhf Packages
  File has unexpected size (27354 != 27478). Mirror sync in progress? [IP: 2a04:4e42:52::729 443]
  Hashes of expected file:
   - Filesize:27478 [weak]
   - SHA512:3cac48f7fec42d716d6f5376ea518cc605428da0a978361d2eacc40f27aa7fc6583fa8fd629c59b95ccf46e8391094c0d1d5aed3f2055357a44e204bc3e67860
   - SHA256:d215ef61beaa16cbfe74dc926d305546e070cfb67814cf57db936362fdb985df
   - SHA1:9be559a23aa29db2e920cb851dcd2ca4ca709ad0 [weak]
   - MD5Sum:a943c884a7351acf0a8f6f7327c6b6f5 [weak]
  Release file created at: Thu, 15 Jul 2021 15:37:51 +0000
Fetched 18.9 kB in 6s (3,305 B/s)
Reading package lists... Done

EDIT: found this: