{"id":1525,"date":"2024-03-23T21:31:31","date_gmt":"2024-03-23T20:31:31","guid":{"rendered":"https:\/\/caipirinha.spdns.org\/wp\/?p=1525"},"modified":"2024-04-03T22:15:24","modified_gmt":"2024-04-03T20:15:24","slug":"grafana-visualizations-part-2","status":"publish","type":"post","link":"https:\/\/caipirinha.spdns.org\/wp\/?p=1525","title":{"rendered":"Grafana Visualizations (Part 2)"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Executive Summary<\/h2>\n\n\n\n<p>In this article, we use <a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;in order to examine real-world data of <strong>electricity consumption<\/strong> stored in a&nbsp;<a href=\"https:\/\/mariadb.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">MariaDB<\/a>&nbsp;database. As <strong>dynamic pricing<\/strong> (<strong>day-ahead market<\/strong>) is used, we also try to investigate how well I have fared so far with dynamic pricing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Background<\/h2>\n\n\n\n<p>On 1<sup>st<\/sup> of March 2024, I switched from a traditional electricity provider to one with dynamic day-ahead pricing, in my case, <a href=\"https:\/\/tibber.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber<\/a>. I wanted to try this contractual model and see if I could successfully manage to shift chunks of high electricity consumption such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&#8230; loading the battery-electric vehicle (BEV) or the plug-in hybrid car (PHEV)<\/li>\n\n\n\n<li>&#8230; washing clothes<\/li>\n\n\n\n<li>&#8230; drying clothes in the electric dryer<\/li>\n<\/ul>\n\n\n\n<p>to those times of the day when the electricity price is lower. I also wanted to see if that makes economic sense for me. And, after all, it is fun to play around with data and gain new insights.<\/p>\n\n\n\n<p>As my electricity supplier, I had chosen <a href=\"https:\/\/tibber.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber<\/a> because they were the first one I got to know and they offer a device called <a href=\"https:\/\/tibber.com\/de\/store\/produkt\/pulse-ir\" target=\"_blank\" rel=\"noreferrer noopener\">Pulse<\/a> which can connect a digital electricity meter to their infrastructure for metering and billing purposes. Furthermore, they do have an API [<a href=\"https:\/\/developer.tibber.com\/docs\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">1<\/a>] which allows me to read out my own data; that was very important for me. I understand that meanwhile, there are several providers <a href=\"https:\/\/tibber.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber<\/a> that have similar models and comparable features.<\/p>\n\n\n\n<p>In my opinion, dynamic electricity prices will play an important role in the future. As we generate ever more energy from renewables (solar and wind power), there are times when a lot of electricity is generated or when we even see over-production, and there are times when less electricity will be produced (&#8220;dunkelflaute&#8221;). Dynamic prices are an excellent tool to motivate people to shift a part of their consumption pattern to times with a large offer in electricity supply (cheap price). An easy-to-understand example is washing clothes during the day in summer (rather than in the evening) when there is a large supply of solar energy; then, the price will experience a local minimum between lunch time and dinner time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Preconditions<\/h2>\n\n\n\n<p>In order to use the approach described here, you should:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2026 have access to a Linux machine or account<\/li>\n\n\n\n<li>\u2026 have a&nbsp;<a href=\"https:\/\/www.mysql.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">MySQL<\/a>&nbsp;or&nbsp;<a href=\"https:\/\/mariadb.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">MariaDB<\/a>&nbsp;database server installed, configured, up and running<\/li>\n\n\n\n<li>\u2026 have a&nbsp;populated&nbsp;<a href=\"https:\/\/www.mysql.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">MySQL<\/a>&nbsp;or&nbsp;<a href=\"https:\/\/mariadb.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">MariaDB<\/a>&nbsp;database like in our example to which you have access<\/li>\n\n\n\n<li>\u2026 have the package&nbsp;<a href=\"https:\/\/grafana.com\/grafana\/download\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;[<a href=\"https:\/\/grafana.com\/grafana\/download\" target=\"_blank\" rel=\"noreferrer noopener\">2<\/a>] installed, configured, up and running<\/li>\n\n\n\n<li>&#8230; have access to the data of your own electricity consumption and pricing information of your supplier or use the dataset linked below in this blog<\/li>\n\n\n\n<li>&#8230; have some understanding of day-ahead pricing in the electricity market [<a href=\"https:\/\/www.sciencedirect.com\/topics\/engineering\/day-ahead-market\" target=\"_blank\" rel=\"noreferrer noopener\">3<\/a>]<\/li>\n\n\n\n<li>\u2026 have some basic knowledge of how to operate in a Linux environment and some basic understanding of shell scripts<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Description and Usage<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">The Database<\/h3>\n\n\n\n<p>The base for the following visualizations is a fully populated <a href=\"https:\/\/mariadb.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">MariaDB<\/a>&nbsp;database with the following structure:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Datenbank f\u00fcr Analysen mit Tibber\n# V1.1; 2023-10-19, Gabriel R\u00fceck &lt;gabriel@rueeck.de&gt;, &lt;gabriel@caipirinha.spdns.org&gt;\n# Delete existing databases\nREVOKE ALL ON tibber.* FROM 'gabriel';\nDROP DATABASE tibber;\n\n# Create a new database\nCREATE DATABASE tibber DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci;\nGRANT ALL ON tibber.* TO 'gabriel';\nUSE tibber;\nSET default_storage_engine=Aria;\n\nCREATE TABLE preise          (zeitstempel    DATETIME NOT NULL,\\\n                              preis          DECIMAL(5,4) NOT NULL,\\\n                              niveau         ENUM('VERY_CHEAP','CHEAP','NORMAL','EXPENSIVE','VERY_EXPENSIVE'));\n\nCREATE TABLE verbrauch       (zeitstempel    DATETIME NOT NULL,\\\n                              energie        DECIMAL(5,3) NOT NULL,\\\n                              kosten         DECIMAL(5,4) NOT NULL);<\/code><\/pre>\n\n\n\n<p>The section <strong>Files<\/strong> at the end of this blog post provides real-world sample data which you can use to populate the database and do your own calculations and graphs. The database contains two tables. The one named <em>preise<\/em> contains the day-ahead prices and some price level tag which is determined by <a href=\"https:\/\/tibber.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber<\/a> themselves according to [<a href=\"https:\/\/developer.tibber.com\/docs\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">1<\/a>]. The second tables named <em>verbrauch<\/em> contains the electrical energy I have consumed, and the cost associated with the consumption. <em>zeitstempel<\/em> in both tables indicates the date and the hour when the respective 1-hour-block with the respective electricity price or the electricity consumption starts. Consequently, the day is divided in 24 blocks of 1 hour. Data from the tables might look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MariaDB &#91;tibber]&gt; SELECT * FROM preise WHERE DATE(zeitstempel)='2024-03-18';\n+---------------------+--------+-----------+\n| zeitstempel         | preis  | niveau    |\n+---------------------+--------+-----------+\n| 2024-03-18 00:00:00 | 0.2658 | NORMAL    |\n| 2024-03-18 01:00:00 | 0.2575 | NORMAL    |\n| 2024-03-18 02:00:00 | 0.2588 | NORMAL    |\n| 2024-03-18 03:00:00 | 0.2601 | NORMAL    |\n| 2024-03-18 04:00:00 | 0.2661 | NORMAL    |\n| 2024-03-18 05:00:00 | 0.2737 | NORMAL    |\n| 2024-03-18 06:00:00 | 0.2922 | NORMAL    |\n| 2024-03-18 07:00:00 | 0.3059 | EXPENSIVE |\n| 2024-03-18 08:00:00 | 0.3019 | EXPENSIVE |\n| 2024-03-18 09:00:00 | 0.2880 | NORMAL    |\n| 2024-03-18 10:00:00 | 0.2761 | NORMAL    |\n| 2024-03-18 11:00:00 | 0.2688 | NORMAL    |\n| 2024-03-18 12:00:00 | 0.2700 | NORMAL    |\n| 2024-03-18 13:00:00 | 0.2707 | NORMAL    |\n| 2024-03-18 14:00:00 | 0.2715 | NORMAL    |\n| 2024-03-18 15:00:00 | 0.2768 | NORMAL    |\n| 2024-03-18 16:00:00 | 0.2834 | NORMAL    |\n| 2024-03-18 17:00:00 | 0.3176 | EXPENSIVE |\n| 2024-03-18 18:00:00 | 0.3629 | EXPENSIVE |\n| 2024-03-18 19:00:00 | 0.3400 | EXPENSIVE |\n| 2024-03-18 20:00:00 | 0.3129 | EXPENSIVE |\n| 2024-03-18 21:00:00 | 0.2861 | NORMAL    |\n| 2024-03-18 22:00:00 | 0.2827 | NORMAL    |\n| 2024-03-18 23:00:00 | 0.2781 | NORMAL    |\n+---------------------+--------+-----------+\n24 rows in set (0,002 sec)\n\nMariaDB &#91;tibber]&gt; SELECT * FROM verbrauch WHERE DATE(zeitstempel)='2024-03-18';\n+---------------------+---------+--------+\n| zeitstempel         | energie | kosten |\n+---------------------+---------+--------+\n| 2024-03-18 00:00:00 |   0.554 | 0.1472 |\n| 2024-03-18 01:00:00 |   0.280 | 0.0721 |\n| 2024-03-18 02:00:00 |   0.312 | 0.0808 |\n| 2024-03-18 03:00:00 |   0.307 | 0.0799 |\n| 2024-03-18 04:00:00 |   0.282 | 0.0750 |\n| 2024-03-18 05:00:00 |   0.315 | 0.0862 |\n| 2024-03-18 06:00:00 |   0.377 | 0.1102 |\n| 2024-03-18 07:00:00 |   0.368 | 0.1126 |\n| 2024-03-18 08:00:00 |   0.275 | 0.0830 |\n| 2024-03-18 09:00:00 |   0.793 | 0.2284 |\n| 2024-03-18 10:00:00 |   1.041 | 0.2875 |\n| 2024-03-18 11:00:00 |   0.453 | 0.1217 |\n| 2024-03-18 12:00:00 |   0.362 | 0.0977 |\n| 2024-03-18 13:00:00 |   0.005 | 0.0014 |\n| 2024-03-18 14:00:00 |   0.027 | 0.0073 |\n| 2024-03-18 15:00:00 |   0.144 | 0.0399 |\n| 2024-03-18 16:00:00 |   0.248 | 0.0703 |\n| 2024-03-18 17:00:00 |   0.363 | 0.1153 |\n| 2024-03-18 18:00:00 |   0.381 | 0.1382 |\n| 2024-03-18 19:00:00 |   0.360 | 0.1224 |\n| 2024-03-18 20:00:00 |   0.354 | 0.1108 |\n| 2024-03-18 21:00:00 |   0.382 | 0.1093 |\n| 2024-03-18 22:00:00 |   0.373 | 0.1055 |\n| 2024-03-18 23:00:00 |   0.417 | 0.1159 |\n+---------------------+---------+--------+\n24 rows in set (0,001 sec)\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Connecting Grafana to the Database<\/h3>\n\n\n\n<p>Now we shall visualize the data in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>.&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;is powerful and mighty visualization tool with which you can create state-of-the-art dashboards and professional visualizations. I must really laude the team behind&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;for making such a powerful tool free for personal and other usage (for details to their licenses und usage models, see&nbsp;<a href=\"https:\/\/grafana.com\/licensing\/\" target=\"_blank\" rel=\"noreferrer noopener\">Licensing | Grafana Labs<\/a>).<\/p>\n\n\n\n<p>Before you can use data from a MySQL database in Grafana, you have to set up MySQL as a data source in&nbsp;<strong>Connections<\/strong>. Remember that MySQL is one of many possible data sources for&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;and so, you have to walk through the jungle of offered data sources and find the MySQL connection and set up your data source accordingly. On my server, both&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/mariadb.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">MariaDB<\/a>&nbsp;run on the same machine, so there is no need for encryption, etc. My setup simply looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"737\" height=\"842\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-12.png\" alt=\"\" class=\"wp-image-1526\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-12.png 737w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-12-263x300.png 263w\" sizes=\"auto, (max-width: 737px) 100vw, 737px\" \/><figcaption class=\"wp-element-caption\">Connection Setup in Grafana<\/figcaption><\/figure>\n\n\n\n<p>One step where I always stumble again is that in the entry mask for the connection setup,&nbsp;<em>localhost:3306<\/em>&nbsp;is proposed in grey color as Host, but unless you type that in, too,&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;will actually not use&nbsp;<em>localhost:3306<\/em>. So be sure to physically type that in.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Populating the Database<\/h3>\n\n\n\n<p><a href=\"https:\/\/tibber.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber<\/a> customers who have created an API token for themselves [<a href=\"https:\/\/developer.tibber.com\/docs\/guides\/calling-api\" target=\"_blank\" rel=\"noreferrer noopener\">4<\/a>] can populate the database with the following <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bash_(Unix_shell)\" target=\"_blank\" rel=\"noreferrer noopener\">bash<\/a> script; in this script, you need to replace <em>_API_TOKEN<\/em> with your personal API token ( [<a href=\"https:\/\/developer.tibber.com\/docs\/guides\/calling-api\" target=\"_blank\" rel=\"noreferrer noopener\">4<\/a>]) and <em>_HOME_ID<\/em> with your personal Home ID ([<a href=\"https:\/\/developer.tibber.com\/docs\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">1<\/a>]). The script further assumes that the user <em>gabriel<\/em> can login to the MySQL database without further authentication; this can be achieved by writing the MySQL login information in the file <strong>~\/.my.cnf<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n#\n# Dieses Skript liest Daten f\u00fcr die Tibber-Datenbank und speichert das Ergebnis in einer MySQL-Datenbank ab.\n# Das Skript wird einmal pro Tag aufgerufen.\n#\n# V1.3; 2024-03-24, Gabriel R\u00fceck &lt;gabriel@rueeck.de&gt;, &lt;gabriel@caipirinha.spdns.org&gt;\n#\n# CONSTANTS\ndeclare -r    MYSQL_DATABASE='tibber'\ndeclare -r    MYSQL_SERVER='localhost'\ndeclare -r    MYSQL_USER='gabriel'\ndeclare -r    TIBBER_API_TOKEN='_API_TOKEN'\ndeclare -r    TIBBER_API_URL='https:\/\/api.tibber.com\/v1-beta\/gql'\ndeclare -r    TIBBER_HOME_ID='_HOME_ID'\n\n# VARIABLES\n\n# PROGRAM\n# Read price information for tomorrow\ncurl -s -S -H \"Authorization: Bearer ${TIBBER_API_TOKEN}\" -H \"Content-Type: application\/json\" -X POST -d  '{ \"query\": \"{viewer {home (id: \\\"'\"${TIBBER_HOME_ID}\"'\\\") {currentSubscription {priceInfo {tomorrow {total startsAt level }}}}}}\" }' \"${TIBBER_API_URL}\" | jq -r '.data.viewer.home.currentSubscription.priceInfo.tomorrow&#91;] | .total, .startsAt, .level' | while read cost; do\n  read LINE\n  read level\n  timestamp=$(echo \"${LINE%%+*}\" | tr 'T' ' ')\n  # Determine timezone offset and store the UTC datetime in the database\n  offset=\"${LINE:23}\"\n  mysql --default-character-set=utf8mb4 -B -N -r -D \"${MYSQL_DATABASE}\" -h ${MYSQL_SERVER} -u ${MYSQL_USER} -e \"INSERT INTO preise (zeitstempel,preis,niveau) VALUES (DATE_SUB(\\\"${timestamp}\\\",INTERVAL \\\"${offset}\\\" HOUR_MINUTE),${cost},\\\"${level}\\\");\"\ndone\n\n# Read consumption information from the past 24 hours\ncurl -s -S -H \"Authorization: Bearer ${TIBBER_API_TOKEN}\" -H \"Content-Type: application\/json\" -X POST -d  '{ \"query\": \"{viewer {home (id: \\\"'\"${TIBBER_HOME_ID}\"'\\\") {consumption (resolution: HOURLY, last: 24) {nodes {from to cost consumption}}}}}\" }' \"${TIBBER_API_URL}\" | jq -r '.data.viewer.home.consumption.nodes&#91;] | .from, .consumption, .cost' | while read LINE; do\n  read consumption\n  read cost\n  timestamp=$(echo \"${LINE%%+*}\" | tr 'T' ' ')\n  # Determine timezone offset and store the UTC datetime in the database\n  offset=\"${LINE:23}\"\n  mysql --default-character-set=utf8mb4 -B -N -r -D \"${MYSQL_DATABASE}\" -h ${MYSQL_SERVER} -u ${MYSQL_USER} -e \"INSERT INTO verbrauch (zeitstempel,energie,kosten) VALUES (DATE_SUB(\\\"${timestamp}\\\",INTERVAL \\\"${offset}\\\" HOUR_MINUTE),${consumption},${cost});\"\ndone<\/code><\/pre>\n\n\n\n<p>In my case, I call this script with <strong>cron<\/strong> once per day, at 14:45 as <a href=\"https:\/\/tibber.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber<\/a> releases the price information for the subsequent day only at 14:00. The script furthermore stores UTC timestamps in the database. <a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a> will adjust them to the local time for graphs of the type <a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/time-series\/\" target=\"_blank\" rel=\"noreferrer noopener\">Time series<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Easy Visualizations<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Price level<\/h4>\n\n\n\n<p>One of my first visualizations was a table that shows the price level tags for today and tomorrow. The idea behind is that I would look at the table once per day during breakfast and immediately identify the sweet spots on where I could charge the car, turn on the washing machine, etc.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"593\" height=\"962\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Price-level.png\" alt=\"\" class=\"wp-image-1527\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Price-level.png 593w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Price-level-185x300.png 185w\" sizes=\"auto, (max-width: 593px) 100vw, 593px\" \/><figcaption class=\"wp-element-caption\">Table with Price Levels<\/figcaption><\/figure>\n\n\n\n<p>For this table, we use the built-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<strong><a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/table\/\" target=\"_blank\" rel=\"noreferrer noopener\">Table<\/a><\/strong>. We select the according database, and our MySQL query is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT IF(DATE(DATE_ADD(zeitstempel,INTERVAL HOUR(TIMEDIFF(SYSDATE(),UTC_TIMESTAMP())) HOUR))=CURDATE(),'TODAY','TOMORROW') AS Tag, HOUR(DATE_ADD(zeitstempel,INTERVAL HOUR(TIMEDIFF(SYSDATE(),UTC_TIMESTAMP())) HOUR)) AS Stunde, niveau\nFROM preise\nWHERE DATE_ADD(zeitstempel,INTERVAL HOUR(TIMEDIFF(SYSDATE(),UTC_TIMESTAMP())) HOUR)&gt;=CURDATE() \nGroup BY Tag, Stunde;<\/code><\/pre>\n\n\n\n<p>The query above lists one price level per line. However, in order to get the nice visualization shown above, we need to transpose the table with respect to the months, and therefore, we must select the built-in transformation&nbsp;<strong>Grouping to Matrix<\/strong>&nbsp;and enter our column names according to the image below:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"847\" height=\"105\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-13.png\" alt=\"\" class=\"wp-image-1528\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-13.png 847w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-13-300x37.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-13-768x95.png 768w\" sizes=\"auto, (max-width: 847px) 100vw, 847px\" \/><figcaption class=\"wp-element-caption\">Grouping to Matrix<\/figcaption><\/figure>\n\n\n\n<p>Now, in order to get a beautiful visualization, we need to adjust some of the&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a>, and those are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Cell options<\/strong> \u2192 <strong>Cell type<\/strong>: Set to&nbsp;<strong>Auto<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Set to&nbsp;<strong>Single color<\/strong><\/li>\n<\/ul>\n\n\n\n<p>and we need to define some <strong>Value mappings<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>NORMAL<\/strong> <strong>\u2192<\/strong> Select yellow color<\/li>\n\n\n\n<li><strong>EXPENSIVE<\/strong> <strong>\u2192<\/strong> Select orange color<\/li>\n\n\n\n<li><strong>VERY_EXPENSIVE<\/strong> <strong>\u2192<\/strong> Select red color<\/li>\n\n\n\n<li><strong>CHEAP<\/strong> <strong>\u2192<\/strong> Select green color<\/li>\n\n\n\n<li><strong>VERY_CHEAP<\/strong> <strong>\u2192<\/strong> Select blue color<\/li>\n<\/ul>\n\n\n\n<p>and we need to define some&nbsp;<strong>Overrides<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Override 1<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>TODAY<\/strong><\/li>\n\n\n\n<li><strong>Override 1<\/strong> \u2192 <strong>Cell options<\/strong> \u2192 <strong>Cell type<\/strong>: Set to&nbsp;<strong>Colored background<\/strong><\/li>\n\n\n\n<li><strong>Override 2<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>TOMORROW<\/strong><\/li>\n\n\n\n<li><strong>Override 2<\/strong> \u2192 <strong>Cell options<\/strong> \u2192 <strong>Cell type<\/strong>: Set to&nbsp;<strong>Colored background<\/strong><\/li>\n\n\n\n<li><strong>Override 3<\/strong> \u2192 <strong>Fields with type<\/strong>: Select&nbsp;<strong>Stunde\\Tag<\/strong><\/li>\n\n\n\n<li><strong>Override 3<\/strong> \u2192 <strong>Column width<\/strong> \u2192 Set to&nbsp;<strong>110<\/strong><\/li>\n\n\n\n<li><strong>Override 3<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Display name<\/strong>: Type <strong>HOUR<\/strong> (That is only necessary because I initially did my query with German column names)<\/li>\n<\/ul>\n\n\n\n<p>In the MySQL query above, you can find the sequence<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DATE_ADD(zeitstempel,INTERVAL HOUR(TIMEDIFF(SYSDATE(),UTC_TIMESTAMP())) HOUR)<\/code><\/pre>\n\n\n\n<p>which actually transforms the UTC timestamp into the timestamp of the local time of the machine where the MySQL server resides. In my case, this is the same machine that I use for Grafana. The sub-sequence<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>HOUR(TIMEDIFF(SYSDATE(),UTC_TIMESTAMP()))<\/code><\/pre>\n\n\n\n<p>gives &#8211; in my case &#8211; back a 2 when we are in summer time as then we are at UTC+2h, and 1 when we are in winter time as then we are at UTC+1h. This sequence was necessary for me as the <a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/table\/\" target=\"_blank\" rel=\"noreferrer noopener\">Table<\/a> does not do an automatic time conversion to the local time.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Electricity price (per kWh) and grid consumption<\/h4>\n\n\n\n<p>In the next visualization, we will look at a timeline of the electricity price per hour and our consumption pattern. This will look like this graph:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"215\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Electricity-price-per-kWh-and-grid-consumption-1024x215.png\" alt=\"Electricity price (per kWh) and grid consumption\" class=\"wp-image-1529\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Electricity-price-per-kWh-and-grid-consumption-1024x215.png 1024w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Electricity-price-per-kWh-and-grid-consumption-300x63.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Electricity-price-per-kWh-and-grid-consumption-768x162.png 768w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Electricity-price-per-kWh-and-grid-consumption-1536x323.png 1536w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Electricity-price-per-kWh-and-grid-consumption.png 2006w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Electricity price (per kWh) and grid consumption<\/figcaption><\/figure>\n\n\n\n<p>For this graph, we use the built-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<strong><a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/time-series\/\" target=\"_blank\" rel=\"noreferrer noopener\">Time series<\/a><\/strong>. We select the according database, and we define two MySQL queries. The first one is named <em>Price<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT zeitstempel,\n       preis AS 'price',\n       AVG(preis) OVER (ORDER BY zeitstempel ROWS BETWEEN 47 PRECEDING AND CURRENT ROW) as 'rolling 2-days average price'\nFROM preise;<\/code><\/pre>\n\n\n\n<p>The first query has the peculiarity that we do not only retrieve the price for each 1-hour block, but that we also calculate a rolling 2-days average over the extracted data. The second query is named <em>Consumption<\/em> and retrieves our energy consumption:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT zeitstempel, energie AS 'grid consumption' FROM verbrauch;<\/code><\/pre>\n\n\n\n<p>Again, we need to adjust some of the&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a>, and those are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>(Euro) \u20ac<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Min<\/strong>: Set to <strong>0<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>2<\/strong><\/li>\n<\/ul>\n\n\n\n<p>and we need to define some&nbsp;<strong>Overrides<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Override 1<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>grid consumption<\/strong><\/li>\n\n\n\n<li><strong>Override 1<\/strong> \u2192 <strong>Axis<\/strong> \u2192 <strong>Placement<\/strong>: Select <strong>Right<\/strong><\/li>\n\n\n\n<li><strong>Override 1<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>Kilowatt-hour (kWh)<\/strong><\/li>\n\n\n\n<li><strong>Override 1<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>1<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In this graph, we can already get an indication on how well we time our energy consumption. Ideally, the peaks (<strong>local maximums<\/strong>) in energy consumption (blue line) should coincide with the <strong>local minimums<\/strong> of the electricity price (green line). As you can see with the two peaks of the blue line (charging the BEV), I did not always match this sweet spot. There might be good reasons for consuming electricity also at hours of higher prices, and some examples are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You have to drive away at a certain hour, and you need to charge the BEV now.<\/li>\n\n\n\n<li>You have solar generation at certain times of the day which you intend to use and therefore consume electricity (like for charging a BEV) when the sun shines. While you then might not consume at the cheapest hour, you might ultimately make good use of the additional solar energy.<\/li>\n\n\n\n<li>You want to watch TV in the evening when the electricity price is typically high.<\/li>\n<\/ul>\n\n\n\n<p>This graph visualizes the data according to the timezone of the dashboard, so there is no need to add an offset to the UTC timestamps in the database.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Heatmap of the Tibber flexible hourly prices per kWh<\/h4>\n\n\n\n<p>In the next visualization, we look at a <strong>heatmap<\/strong> of the hourly prices and therefore, we use the plug-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<a href=\"https:\/\/grafana.com\/grafana\/plugins\/marcusolsson-hourly-heatmap-panel\/\" target=\"_blank\" rel=\"noreferrer noopener\"><strong>Hourly heatmap<\/strong><\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1005\" height=\"345\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Heatmap-of-the-Tibber-flexible-hourly-prices-per-kWh.png\" alt=\"\" class=\"wp-image-1530\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Heatmap-of-the-Tibber-flexible-hourly-prices-per-kWh.png 1005w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Heatmap-of-the-Tibber-flexible-hourly-prices-per-kWh-300x103.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Heatmap-of-the-Tibber-flexible-hourly-prices-per-kWh-768x264.png 768w\" sizes=\"auto, (max-width: 1005px) 100vw, 1005px\" \/><figcaption class=\"wp-element-caption\">Hourly heatmap of the day-ahead electricity prices<\/figcaption><\/figure>\n\n\n\n<p>The query is very simple:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT UNIX_TIMESTAMP(DATE_ADD(zeitstempel,INTERVAL HOUR(TIMEDIFF(SYSDATE(),UTC_TIMESTAMP())) HOUR)) AS time, preis FROM preise;<\/code><\/pre>\n\n\n\n<p>However, we need to adjust some of the&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a>, and those are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Dimensions<\/strong> \u2192 <strong>Time<\/strong>: Select <strong>time<\/strong><\/li>\n\n\n\n<li><strong><strong>Dimensions<\/strong><\/strong> \u2192 <strong>Value<\/strong>: Select <strong>price<\/strong><\/li>\n\n\n\n<li><strong>Hourly heatmap<\/strong> \u2192 <strong>From<\/strong>: Set to <strong>00:00<\/strong><\/li>\n\n\n\n<li><strong>Hourly heatmap<\/strong> \u2192 <strong>To<\/strong>: Set to <strong>00:00<\/strong><\/li>\n\n\n\n<li><strong>Hourly heatmap<\/strong> \u2192 <strong>Group by<\/strong>: Select <strong>60 minutes<\/strong><\/li>\n\n\n\n<li><strong>Hourly heatmap<\/strong> \u2192 <strong>Calculation<\/strong>: Select <strong>Sum<\/strong><\/li>\n\n\n\n<li><strong>Hourly heatmap<\/strong> \u2192 <strong>Color palette<\/strong>: Select <strong>Spectral<\/strong><\/li>\n\n\n\n<li><strong>Hourly heatmap<\/strong> \u2192 <strong>Invert color palette \u2192<\/strong> Activate<\/li>\n\n\n\n<li><strong>Legend<\/strong> \u2192 <strong>Show legend \u2192<\/strong> Activate<\/li>\n\n\n\n<li><strong>Legend<\/strong> \u2192 <strong>Gradient quality<\/strong>: Select <strong>Low<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>(Euro) \u20ac<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>2<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>From thresholds (by value)<\/strong><\/li>\n<\/ul>\n\n\n\n<p>With the heatmap, we have an easy-to-understand visualization on when the prices are high and on when they are low and on whether there is a regular pattern that we can observe. In this case, we can identify that in the evening (at dinner or TV time), the electricity price often seems to be high. Hence, this is not a good time to switch on powerful electric consumers or to start charging a BEV.<\/p>\n\n\n\n<p>Similar to the <a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/table\/\" target=\"_blank\" rel=\"noreferrer noopener\">Table<\/a>, you can find the sequence<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>DATE_ADD(zeitstempel,INTERVAL HOUR(TIMEDIFF(SYSDATE(),UTC_TIMESTAMP())) HOUR)<\/code><\/pre>\n\n\n\n<p>because the <a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/table\/\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a><a href=\"https:\/\/grafana.com\/grafana\/plugins\/marcusolsson-hourly-heatmap-panel\/\" target=\"_blank\" rel=\"noreferrer noopener\">Hourly heatmap<\/a> also does not do an automatic time conversion to the local time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Complex Visualizations<\/h3>\n\n\n\n<h4 class=\"wp-block-heading\">Actual cost versus minimal cost, maximal cost, average cost per day<\/h4>\n\n\n\n<p>This visualization shows the daily electricity cost that I have incurred (blue line) and the cost I would have incurred if I had purchased the whole amount of electricity on the respective day:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&#8230; during the <strong>cheapest hour<\/strong> on that day (green line)<\/li>\n\n\n\n<li>&#8230; during the <strong>most expensive hour<\/strong> on that day (red line)<\/li>\n\n\n\n<li>&#8230; at an <strong>average price<\/strong> (average of all hours) on that day (yellow line)<\/li>\n<\/ul>\n\n\n\n<p>The closer the blue line is to the green line, the better I have shifted my consumption pattern to the hours of cheap electricity. In real life, one will always have to purchase electricity also in hours of expensive electricity unless one switches off all devices in a household at certain hours. So, in real life, the blue line will never be the same as the green line. A blue line between the yellow and the green line already indicates that one does well. The graph also shows that my consumption varies substantially from day to day. The graph uses the built-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<strong><a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/time-series\/\" target=\"_blank\" rel=\"noreferrer noopener\">Time series<\/a><\/strong>. The last data point must not be considered as the last day is only calculated until 14:00 local time.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1007\" height=\"347\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Actual-cost-versus-minimal-cost-maximal-cost-average-cost-per-day.png\" alt=\"\" class=\"wp-image-1533\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Actual-cost-versus-minimal-cost-maximal-cost-average-cost-per-day.png 1007w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Actual-cost-versus-minimal-cost-maximal-cost-average-cost-per-day-300x103.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Actual-cost-versus-minimal-cost-maximal-cost-average-cost-per-day-768x265.png 768w\" sizes=\"auto, (max-width: 1007px) 100vw, 1007px\" \/><figcaption class=\"wp-element-caption\">Actual cost versus minimal cost, maximal cost, average cost per day<\/figcaption><\/figure>\n\n\n\n<p>For this graph, we join the tables <em>preise<\/em> and <em>verbrauch<\/em> in a MySQL query and group the result by day:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT DATE(preise.zeitstempel) AS 'date',\n       MIN(preise.preis)*SUM(verbrauch.energie) AS 'minimal cost',\n       MAX(preise.preis)*SUM(verbrauch.energie) AS 'maximal cost',\n       AVG(preise.preis)*SUM(verbrauch.energie) AS 'average cost',\n       SUM(verbrauch.kosten) AS 'actual cost'\nFROM preise JOIN verbrauch ON verbrauch.zeitstempel=preise.zeitstempel\nWHERE DATE(preise.zeitstempel)&gt;'2024-03-03'\nGROUP BY DATE(preise.zeitstempel);<\/code><\/pre>\n\n\n\n<p>The following&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a> are recommended:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>(Euro) \u20ac<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>2<\/strong><\/li>\n<\/ul>\n\n\n\n<p>and the following <strong>Overrides<\/strong> are recommended:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Override 1<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>minimal cost<\/strong><\/li>\n\n\n\n<li><strong>Override 1<\/strong> \u2192 <strong>Standard options \u2192 Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>green<\/strong><\/li>\n\n\n\n<li><strong>Override 2<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>maximal cost<\/strong><\/li>\n\n\n\n<li><strong>Override 2<\/strong> \u2192 <strong>Standard options \u2192 Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>red<\/strong><\/li>\n\n\n\n<li><strong>Override 3<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>actual cost<\/strong><\/li>\n\n\n\n<li><strong>Override 3<\/strong> \u2192 <strong>Standard options \u2192 Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>blue<\/strong><\/li>\n\n\n\n<li><strong>Override 4<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>average cost<\/strong><\/li>\n\n\n\n<li><strong>Override 4<\/strong> <strong>\u2192 Standard options \u2192 Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>yellow<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Important: This graph adds up the data from a UTC day (not the local calendar day) and visualizes the data points according to the timezone of the dashboard.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Cumulated savings versus various fictive static electricity prices<\/h4>\n\n\n\n<p>This visualization shows us in a cumulative manner how much money I have saved using dynamic pricing versus fictive electricity contracts with different static prices per kWh (traditional contracts). The graph uses the built-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<strong><a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/time-series\/\" target=\"_blank\" rel=\"noreferrer noopener\">Time series<\/a><\/strong>. The last data point must not be considered as the last day is only calculated until 14:00 local time.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1003\" height=\"346\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cumulated-savings-versus-various-fictive-static-electricity-prices.png\" alt=\"\" class=\"wp-image-1534\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cumulated-savings-versus-various-fictive-static-electricity-prices.png 1003w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cumulated-savings-versus-various-fictive-static-electricity-prices-300x103.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cumulated-savings-versus-various-fictive-static-electricity-prices-768x265.png 768w\" sizes=\"auto, (max-width: 1003px) 100vw, 1003px\" \/><figcaption class=\"wp-element-caption\">Cumulated savings versus various fictive static electricity prices<\/figcaption><\/figure>\n\n\n\n<p>One can see that for traditional prices below 27 \u00a2\/kWh, I would not have saved any money so far. 27 \u00a2\/kWh is the price that I could get in a traditional electricity contract at the place where I live. However, it is too early yet to draw final conclusions. I intend to observe how the graphs advance when we get into summer as I expect that during summer, I will have more times at cheap electricity whereas in the subsequent winter, I will probably have more times at higher prices. The graph is done with this query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT DATE(preise.zeitstempel) AS 'Datum',\n       SUM(0.25*SUM(verbrauch.energie)-SUM(verbrauch.kosten)) OVER (ORDER BY DATE(preise.zeitstempel)) as '25 \u00a2\/kWh',\n       SUM(0.26*SUM(verbrauch.energie)-SUM(verbrauch.kosten)) OVER (ORDER BY DATE(preise.zeitstempel)) as '26 \u00a2\/kWh',\n       SUM(0.27*SUM(verbrauch.energie)-SUM(verbrauch.kosten)) OVER (ORDER BY DATE(preise.zeitstempel)) as '27 \u00a2\/kWh',\n       SUM(0.28*SUM(verbrauch.energie)-SUM(verbrauch.kosten)) OVER (ORDER BY DATE(preise.zeitstempel)) as '28 \u00a2\/kWh',\n       SUM(0.29*SUM(verbrauch.energie)-SUM(verbrauch.kosten)) OVER (ORDER BY DATE(preise.zeitstempel)) as '29 \u00a2\/kWh'\nFROM preise JOIN verbrauch ON verbrauch.zeitstempel=preise.zeitstempel\nWHERE DATE(preise.zeitstempel)&gt;'2024-03-03'\nGROUP BY DATE(preise.zeitstempel);<\/code><\/pre>\n\n\n\n<p>The following&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a> are recommended:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>(Euro) \u20ac<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>2<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Important: This graph adds up the data from a UTC day (not the local calendar day) and visualizes the data points according to the timezone of the dashboard.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Daily savings using Tibber flexible versus a fictive static price of 27 \u00a2\/kWh<\/h4>\n\n\n\n<p>This next visualization shows how much money I have saved (green) or lost (red) using dynamic pricing versus a fictive electricity contract with a price of 27 \u00a2\/kWh that &#8211; as mentioned before &#8211; I could get in a traditional electricity contract at the place where I live. The graph uses the built-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<strong><a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/bar-chart\/\" target=\"_blank\" rel=\"noreferrer noopener\">Bar chart<\/a><\/strong>. The last data point must not be considered as the last day is only calculated until 14:00 local time.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1002\" height=\"345\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-a-fictive-static-price-of-27-\u00a2-per-kWh.png\" alt=\"\" class=\"wp-image-1535\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-a-fictive-static-price-of-27-\u00a2-per-kWh.png 1002w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-a-fictive-static-price-of-27-\u00a2-per-kWh-300x103.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-a-fictive-static-price-of-27-\u00a2-per-kWh-768x264.png 768w\" sizes=\"auto, (max-width: 1002px) 100vw, 1002px\" \/><figcaption class=\"wp-element-caption\">Daily savings using Tibber flexible versus a fictive static price of 27 \u00a2\/kWh<\/figcaption><\/figure>\n\n\n\n<p>One can see that due to the nature of dynamic prices, I do not save money every day. It has been quite a mixed result so far. The graph is done with this query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT DATE_FORMAT(preise.zeitstempel,'%m\/%d') AS 'Datum',\n       0.27*SUM(verbrauch.energie)-SUM(verbrauch.kosten) AS 'Daily cost vs. average'\nFROM preise JOIN verbrauch ON verbrauch.zeitstempel=preise.zeitstempel\nWHERE DATE(preise.zeitstempel)&gt;'2024-03-03'\nGROUP BY DATE(preise.zeitstempel);<\/code><\/pre>\n\n\n\n<p>The following&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a> are recommended:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Bar chart<\/strong> \u2192 <strong>Color by field<\/strong>: Select <strong>Daily cost vs. average<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>(Euro) \u20ac<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>2<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>From thresholds (by value)<\/strong><\/li>\n\n\n\n<li><strong>Thresholds<\/strong> \u2192 Enter <strong>0<\/strong>, then select <strong>green<\/strong><\/li>\n\n\n\n<li><strong>Thresholds<\/strong> \u2192 <strong>Base<\/strong>: Select <strong>red<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Important: This graph adds up the data from a UTC day (not the local calendar day).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Daily savings using Tibber flexible versus Tibber daily average price<\/h4>\n\n\n\n<p>A similar visualization shows how much money I have saved (green) or lost (red) using dynamic pricing versus the average price per day, calculated on all dynamic prices of that day. This graph shows me if I am successful in making use of dynamic pricing (green) or not (red). The graph uses the built-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<strong><a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/bar-chart\/\" target=\"_blank\" rel=\"noreferrer noopener\">Bar chart<\/a><\/strong>. The last data point must not be considered as the last day is only calculated until 14:00 local time.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1003\" height=\"345\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-Tibber-daily-average-price.png\" alt=\"\" class=\"wp-image-1536\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-Tibber-daily-average-price.png 1003w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-Tibber-daily-average-price-300x103.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Daily-savings-using-Tibber-flexible-versus-Tibber-daily-average-price-768x264.png 768w\" sizes=\"auto, (max-width: 1003px) 100vw, 1003px\" \/><figcaption class=\"wp-element-caption\">Daily savings using Tibber flexible versus Tibber daily average price<\/figcaption><\/figure>\n\n\n\n<p>So far, it seems that while I do have &#8220;good&#8221; and &#8220;bad&#8221; days, on on the good days, I seem to save more money compared to the <a href=\"https:\/\/tibber.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber<\/a> average price. The large green bars are those where I charge the BEV, and before I charge the BEV, I really carefully consider the electricity price of today and tomorrow. This graph is done with this query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT DATE_FORMAT(preise.zeitstempel,'%m\/%d') AS 'Datum',\n       AVG(preise.preis)*SUM(verbrauch.energie)-SUM(verbrauch.kosten) AS 'Daily cost vs. average'\nFROM preise JOIN verbrauch ON verbrauch.zeitstempel=preise.zeitstempel\nWHERE DATE(preise.zeitstempel)&gt;'2024-03-03'\nGROUP BY DATE(preise.zeitstempel);<\/code><\/pre>\n\n\n\n<p>The following&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a> are recommended:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Bar chart<\/strong> \u2192 <strong>Color by field<\/strong>: Select <strong>Daily cost vs. average<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>(Euro) \u20ac<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>2<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>From thresholds (by value)<\/strong><\/li>\n\n\n\n<li><strong>Thresholds<\/strong> \u2192 Enter <strong>0<\/strong>, then select <strong>green<\/strong><\/li>\n\n\n\n<li><strong>Thresholds<\/strong> \u2192 <strong>Base<\/strong>: Select <strong>red<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Important: This graph adds up the data from a UTC day (not the local calendar day).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Cost of purchased electricity from grid with price indication<\/h4>\n\n\n\n<p>This is one of my favorite graphs as it contains a lot of information in one visualization. It shows the electricity cost per day, but also, how this cost is composed. Each day is a concatenation of 24 rectangles. The 24 rectangles represent the 24 hours of the day. Their color is different, ranging in shades from green to red. The green only rectangle (rgb: 0, 255, 0) is the cost that incurred at the cheapest hour of the day. The red only rectangle (rgb: 255, 0, 0) is the cost that incurred at the most expensive hour of the day. The shades in between ranging from green to red represent an ordered list of the hours from cheap to expensive. Large rectangles mean that a large part of the daily cost can be attributed to a consumption in that hour. Essentially, this means that the more green shades a day has, the more cost has incurred at hours of cheap electricity and the better I have used the dynamic pricing for me. The more red shades a day has, the more cost has incurred at hours of expensive electricity. A day with more red shades is not automatically a &#8220;bad&#8221; day. There might be reasons for a consumption at expensive hours, and some which are true in my case, are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I might cover the electricity demand at cheap hours by my solar panels so that during these hours, I do not have any grid consumption at all.<\/li>\n\n\n\n<li>I might deliberately decide to consume electricity at expensive hours during daylight because my solar panels cover a large part of the consumption at my home, maybe, because I charge the car and 50% of the electric energy comes from the solar panels anyway and I just buy the remaining 50% from the grid. While the grid consumption might be expensive, I anyway get 50% &#8220;for free&#8221; from the solar panels.<\/li>\n\n\n\n<li>I might deliberately decide to consume electricity at expensive hours because the ambient temperature outside the house is moderate or warm and I can heat the house with the air conditioner at high efficiency while I can switch off the central heating which runs by natural gas. In that case, even at high prices, I expect to have a better outcome overall because I might be able to switch off the central heating completely.<\/li>\n<\/ul>\n\n\n\n<p>The graph uses the built-in&nbsp;<a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;visualization&nbsp;<strong><a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/visualizations\/bar-chart\/\" target=\"_blank\" rel=\"noreferrer noopener\">Bar chart<\/a><\/strong>. The last data point must not be considered as the last day is only calculated until 14:00 local time.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1002\" height=\"345\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cost-of-purchased-electricity-from-grid-with-price-indication.png\" alt=\"\" class=\"wp-image-1538\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cost-of-purchased-electricity-from-grid-with-price-indication.png 1002w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cost-of-purchased-electricity-from-grid-with-price-indication-300x103.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/Cost-of-purchased-electricity-from-grid-with-price-indication-768x264.png 768w\" sizes=\"auto, (max-width: 1002px) 100vw, 1002px\" \/><figcaption class=\"wp-element-caption\">Cost of purchased electricity from grid with price indication<\/figcaption><\/figure>\n\n\n\n<p>This graph uses this query:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT DATE_FORMAT(preise.zeitstempel,'%m\/%d') AS 'Datum',\n       ROW_NUMBER() OVER (PARTITION BY DATE(preise.zeitstempel) ORDER BY preise.preis ASC) AS 'Row',\n\t   verbrauch.kosten AS 'Kosten'\nFROM preise JOIN verbrauch ON verbrauch.zeitstempel=preise.zeitstempel\nWHERE DATE(preise.zeitstempel)&gt;'2024-03-03'\nORDER BY DATE(preise.zeitstempel) ASC, preise.preis ASC;<\/code><\/pre>\n\n\n\n<p>and the built-in transformation&nbsp;<strong>Grouping to Matrix<\/strong>:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"872\" height=\"168\" src=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-14.png\" alt=\"\" class=\"wp-image-1539\" srcset=\"https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-14.png 872w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-14-300x58.png 300w, https:\/\/caipirinha.spdns.org\/wp\/wp-content\/uploads\/image-14-768x148.png 768w\" sizes=\"auto, (max-width: 872px) 100vw, 872px\" \/><figcaption class=\"wp-element-caption\">Grouping to Matrix<\/figcaption><\/figure>\n\n\n\n<p>The following&nbsp;<a href=\"https:\/\/grafana.com\/docs\/grafana\/latest\/panels-visualizations\/configure-panel-options\/\" target=\"_blank\" rel=\"noreferrer noopener\">panel options<\/a> must be used:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Standard options<\/strong> \u2192 <strong>Unit<\/strong>: Select <strong>(Euro) \u20ac<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Min<\/strong>: Set to <strong>0<\/strong><\/li>\n\n\n\n<li><strong>Standard options<\/strong> \u2192 <strong>Decimals<\/strong>: Set to <strong>2<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Additionally, we need to define exactly 24 <strong>Overrides<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Override 1<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>1<\/strong><\/li>\n\n\n\n<li><strong>Override 1<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(0, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 2<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>2<\/strong><\/li>\n\n\n\n<li><strong>Override 2<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(22, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 3<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>3<\/strong><\/li>\n\n\n\n<li><strong>Override 3<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(44, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 4<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>4<\/strong><\/li>\n\n\n\n<li><strong>Override 4<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(66, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 5<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>5<\/strong><\/li>\n\n\n\n<li><strong>Override 5<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(89, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 6<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>6<\/strong><\/li>\n\n\n\n<li><strong>Override 6<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(111, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 7<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>7<\/strong><\/li>\n\n\n\n<li><strong>Override 7<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(133, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 8<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>8<\/strong><\/li>\n\n\n\n<li><strong>Override 8<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(155, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 9<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>9<\/strong><\/li>\n\n\n\n<li><strong>Override 9<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(177, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 10<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>10<\/strong><\/li>\n\n\n\n<li><strong>Override 10<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(199, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 11<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>11<\/strong><\/li>\n\n\n\n<li><strong>Override 11<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(222, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 12<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>12<\/strong><\/li>\n\n\n\n<li><strong>Override 12<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(244, 255, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 13<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>13<\/strong><\/li>\n\n\n\n<li><strong>Override 13<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 244, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 14<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>14<\/strong><\/li>\n\n\n\n<li><strong>Override 14<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 222, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 15<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>15<\/strong><\/li>\n\n\n\n<li><strong>Override 15<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 200, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 16<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>16<\/strong><\/li>\n\n\n\n<li><strong>Override 16<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 177, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 17<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>17<\/strong><\/li>\n\n\n\n<li><strong>Override 17<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 155, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 18<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>18<\/strong><\/li>\n\n\n\n<li><strong>Override 18<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 133, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 19<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>19<\/strong><\/li>\n\n\n\n<li><strong>Override 19<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 110, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 20<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>20<\/strong><\/li>\n\n\n\n<li><strong>Override 20<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 89, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 21<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>21<\/strong><\/li>\n\n\n\n<li><strong>Override 21<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 66, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 22<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>22<\/strong><\/li>\n\n\n\n<li><strong>Override 22<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 44, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 23<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>23<\/strong><\/li>\n\n\n\n<li><strong>Override 23<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 22, 0)<\/strong><\/li>\n\n\n\n<li><strong>Override 24<\/strong> \u2192 <strong>Fields with name<\/strong>: Select&nbsp;<strong>24<\/strong><\/li>\n\n\n\n<li><strong>Override 24<\/strong> \u2192 <strong>Standard options<\/strong> \u2192 <strong>Color scheme<\/strong>: Select <strong>Single color<\/strong>, then select <strong>Custom<\/strong>, then<strong> rgb(255, 0, 0)<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Important: This graph adds up the data from a UTC day (not the local calendar day).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>Even with a relatively simple dataset, we can create insightful visualizations with <a href=\"https:\/\/grafana.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Grafana<\/a>&nbsp;that can help us to interpret complex relationships. In my case, the visualizations shall help me to answer the questions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Do I fare well with dynamic pricing as compared to a traditional electricity contract with static prices?<\/li>\n\n\n\n<li>Am I able to shift consumption pattern of large energy chunks efficiently to those hours where electricity is cheaper?<\/li>\n<\/ul>\n\n\n\n<p>As I mentioned, there might be reasons to buy electricity also at expensive hours. The fact that I have support of solar panels during the day might tilt the decision to consume electric energy aways from the cheapest hours to hours where a large part of that consumption is anyway covered by the solar panels. Or I might decide to heat with the air conditioners because the temperature difference between outside and inside of the house is small and the air conditioners can run with a high efficiency. In that case, I trade in natural gas consumption versus electricity consumption.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Outlook<\/h2>\n\n\n\n<p>It would be interesting to consider the energy that the solar panels generate &#8220;for free&#8221; (not really for free, but as they have been installed, they are already &#8220;sunk cost&#8221;) and visualize the resulting electricity cost from the mix of solar energy with energy consumed from the grid.<\/p>\n\n\n\n<p>Likewise, it might be interesting as well as challenging to derive a good model that uses a battery and dynamic electricity prices as well as the energy from the solar panels to minimize cost of the energy consumption from the grid. How large should this battery be? When should it be charged from the grid and when should it return its energy to the consumers in the house?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Files<\/h2>\n\n\n\n<p>The following dataset was used for the graphs:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/caipirinha.spdns.org\/~gabriel\/Blog\/tibber.sql.gz\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/caipirinha.spdns.org\/~gabriel\/Blog\/tibber.sql.gz<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Sources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>[<a href=\"https:\/\/developer.tibber.com\/docs\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">1<\/a>] =&nbsp;<a href=\"https:\/\/developer.tibber.com\/docs\/overview\">Tibber Developer<\/a><\/li>\n\n\n\n<li>[<a href=\"https:\/\/grafana.com\/grafana\/download\" target=\"_blank\" rel=\"noreferrer noopener\">2<\/a>] =&nbsp;<a href=\"https:\/\/grafana.com\/grafana\/download\" target=\"_blank\" rel=\"noreferrer noopener\">Download Grafana | Grafana Labs<\/a><\/li>\n\n\n\n<li>[<a href=\"https:\/\/www.sciencedirect.com\/topics\/engineering\/day-ahead-market\" target=\"_blank\" rel=\"noreferrer noopener\">3<\/a>] = <a href=\"https:\/\/www.sciencedirect.com\/topics\/engineering\/day-ahead-market\" target=\"_blank\" rel=\"noreferrer noopener\">day-ahead market &#8211; an overview<\/a><\/li>\n\n\n\n<li>[<a href=\"https:\/\/developer.tibber.com\/docs\/guides\/calling-api\" target=\"_blank\" rel=\"noreferrer noopener\">4<\/a>] = <a href=\"https:\/\/developer.tibber.com\/docs\/guides\/calling-api\" target=\"_blank\" rel=\"noreferrer noopener\">Tibber Developer: Communicating with the API<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Disclaimer<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Program codes and examples are for demonstration purposes only.<\/li>\n\n\n\n<li>Program codes are not recommended be used in production environments without further enhancements in terms of speed, failure-tolerance or cyber-security.<\/li>\n\n\n\n<li>While program codes have been tested, they might still contain errors.<\/li>\n\n\n\n<li>I am in neither affiliated nor linked to companies named in this blog post.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we use Grafana\u00a0in order to examine real-world data of electricity consumption stored in a\u00a0MariaDB\u00a0database. As dynamic pricing (day-ahead market) is used, we also try to investigate how well we have fared so far with dynamic pricing.<\/p>\n","protected":false},"author":1,"featured_media":1538,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[108,35,107],"tags":[114,112,113],"class_list":["post-1525","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-energy-transition","category-it","category-statistics","tag-day-ahead","tag-grafana","tag-tibber"],"_links":{"self":[{"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=\/wp\/v2\/posts\/1525","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1525"}],"version-history":[{"count":12,"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=\/wp\/v2\/posts\/1525\/revisions"}],"predecessor-version":[{"id":1553,"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=\/wp\/v2\/posts\/1525\/revisions\/1553"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=\/wp\/v2\/media\/1538"}],"wp:attachment":[{"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1525"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1525"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/caipirinha.spdns.org\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1525"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}