211 lines
5.3 KiB
C
211 lines
5.3 KiB
C
/*
|
|
* fbdash.c
|
|
*
|
|
* Adapted by Florian Klemenz for use in the fb_dash project
|
|
*
|
|
* Source and all credit goes to
|
|
* http://raspberrycompote.blogspot.com/
|
|
* --------------------------------------------------------------------------------------------
|
|
*
|
|
* http://raspberrycompote.blogspot.ie/2014/03/low-level-graphics-on-raspberry-pi-part_14.html
|
|
*
|
|
* Original work by J-P Rosti (a.k.a -rst- and 'Raspberry Compote')
|
|
*
|
|
* Licensed under the Creative Commons Attribution 3.0 Unported License
|
|
* (http://creativecommons.org/licenses/by/3.0/deed.en_US)
|
|
*
|
|
* Distributed in the hope that this will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <sys/mman.h>
|
|
#include <fcntl.h>
|
|
#include <float.h>
|
|
|
|
#include <mysql.h>
|
|
|
|
#include "fblib.h"
|
|
|
|
#define WIDTH 240
|
|
#define HEIGHT 320
|
|
|
|
char *fbp = 0;
|
|
|
|
|
|
|
|
struct s_sourcedata {
|
|
char* text;
|
|
char* temperature;
|
|
char* humidity;
|
|
};
|
|
typedef struct s_sourcedata sourcedata;
|
|
|
|
void finish_with_error(MYSQL *con) {
|
|
fprintf(stderr, "%s\n", mysql_error(con));
|
|
mysql_close(con);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
void updateData() {
|
|
// query database for latest values
|
|
printf("MySQL client version: %s\n", mysql_get_client_info());
|
|
MYSQL *con = mysql_init(NULL);
|
|
if (con == NULL) {
|
|
fprintf(stderr, "%s\n", mysql_error(con));
|
|
exit(1);
|
|
}
|
|
if (mysql_real_connect(con, "web-pi", "grafanaReader", "grafanaReader", "grafanaData", 0, NULL, 0) == NULL) {
|
|
fprintf(stderr, "%s\n", mysql_error(con));
|
|
mysql_close(con);
|
|
exit(1);
|
|
}
|
|
char* query = "\
|
|
SELECT \
|
|
time, \
|
|
source, \
|
|
metric, \
|
|
value \
|
|
FROM readings AS r \
|
|
INNER JOIN sources AS s ON r.source_id = s.id \
|
|
INNER JOIN metrics AS m ON r.metric_id = m.id \
|
|
WHERE \
|
|
time > (NOW() - 60 * 15) AND \
|
|
metric IN ('Luftfeuchte','Temperatur') AND \
|
|
source IN ('Esszimmer','Wohnzimmer') \
|
|
ORDER BY time DESC \
|
|
LIMIT 100;";
|
|
|
|
printf("%s\n",query);
|
|
|
|
if (mysql_query(con, query)) {
|
|
finish_with_error(con);
|
|
}
|
|
MYSQL_RES *result = mysql_store_result(con);
|
|
if (result == NULL) {
|
|
finish_with_error(con);
|
|
}
|
|
|
|
sourcedata esszimmer = { "Esszimmer", NULL, NULL };
|
|
sourcedata wohnzimmer = { "Wohnzimmer", NULL, NULL };
|
|
|
|
int num_fields = mysql_num_fields(result);
|
|
MYSQL_ROW row;
|
|
while ((row = mysql_fetch_row(result))) {
|
|
row[3][5] = '\0'; // loose the third decimal ...
|
|
|
|
// data binding
|
|
if (strcmp(row[1], "Esszimmer") == 0) {
|
|
if (strcmp(row[2], "Temperatur") == 0 && esszimmer.temperature == NULL) esszimmer.temperature = row[3];
|
|
else if (strcmp(row[2], "Luftfeuchte") == 0 && esszimmer.humidity == NULL) esszimmer.humidity = row[3];
|
|
}
|
|
if (strcmp(row[1], "Wohnzimmer") == 0) {
|
|
if (strcmp(row[2], "Temperatur") == 0 && wohnzimmer.temperature == NULL) wohnzimmer.temperature = row[3];
|
|
else if (strcmp(row[2], "Luftfeuchte") == 0 && wohnzimmer.humidity == NULL) wohnzimmer.humidity = row[3];
|
|
}
|
|
|
|
// debugging
|
|
for(int i = 0; i < num_fields; i++) {
|
|
printf("%s ", row[i] ? row[i] : "NULL");
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
render_string(fbp, ubuntu_mono_24, esszimmer.text, 15, 7, 255, 255, 255);
|
|
|
|
render_string(fbp, ubuntu_mono_48, esszimmer.temperature, 115, -2, 255, 255, 255);
|
|
render_string(fbp, ubuntu_mono_48, "C", 200, -2, 255, 255, 255);
|
|
|
|
render_string(fbp, ubuntu_mono_48, esszimmer.humidity, 115, 33, 255, 255, 255);
|
|
render_string(fbp, ubuntu_mono_48, "%", 200, 33, 255, 255, 255);
|
|
|
|
|
|
|
|
render_string(fbp, ubuntu_mono_24, wohnzimmer.text, 15, 87, 255, 255, 255);
|
|
|
|
render_string(fbp, ubuntu_mono_48, wohnzimmer.temperature, 115, 77, 255, 255, 255);
|
|
render_string(fbp, ubuntu_mono_48, "C", 200, 77, 255, 255, 255);
|
|
|
|
render_string(fbp, ubuntu_mono_48, wohnzimmer.humidity, 115, 113, 255, 255, 255);
|
|
render_string(fbp, ubuntu_mono_48, "%", 200, 113, 255, 255, 255);
|
|
|
|
mysql_free_result(result);
|
|
mysql_close(con);
|
|
|
|
}
|
|
|
|
void draw() {
|
|
clear_screen(fbp);
|
|
|
|
// horizontal spacersint x_space = 10;
|
|
int y_step_width = HEIGHT / 4;
|
|
for (int i = 1; i < 4; i++) {
|
|
int x0 = 15;
|
|
int x1 = WIDTH - x0;
|
|
int y = y_step_width * i;
|
|
|
|
int r = 225;
|
|
int g = 32;
|
|
int b = 32;
|
|
|
|
draw_line(fbp, x0, y-1, x1, y-1, r, g, b);
|
|
draw_line(fbp, x0, y , x1, y , r, g, b);
|
|
draw_line(fbp, x0, y+1, x1, y+1, r, g, b);
|
|
}
|
|
|
|
|
|
updateData();
|
|
/*
|
|
char *text = "Hell O_o!";
|
|
render_string(fbp, ubuntu_mono_48, text, 15, 0, 255, 255, 255);
|
|
render_string(fbp, ubuntu_mono_24, text, 15, 50, 255, 255, 255);
|
|
render_string(fbp, basic_8, text, 15, 100, 255, 255, 255);
|
|
*/
|
|
}
|
|
|
|
|
|
// application entry point
|
|
int main(int argc, char* argv[])
|
|
{
|
|
int fbfd = 0;
|
|
long int screensize = 0;
|
|
|
|
// Open the framebuffer file for reading and writing
|
|
fbfd = open("/dev/fb1", O_RDWR);
|
|
if (fbfd == -1) {
|
|
printf("Error: cannot open framebuffer device.\n");
|
|
return(1);
|
|
}
|
|
printf("The framebuffer device was opened successfully.\n");
|
|
|
|
// map fb to user mem
|
|
screensize = WIDTH*HEIGHT*2;
|
|
fbp = (char*)mmap(0,
|
|
screensize,
|
|
PROT_READ | PROT_WRITE,
|
|
MAP_SHARED,
|
|
fbfd,
|
|
0);
|
|
|
|
if ((int)fbp == -1) {
|
|
printf("Failed to mmap.\n");
|
|
}
|
|
else {
|
|
// draw...
|
|
draw();
|
|
}
|
|
|
|
// cleanup
|
|
//clear_screen(fbp);
|
|
munmap(fbp, screensize);
|
|
close(fbfd);
|
|
|
|
return 0;
|
|
}
|