Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple cm160 #12

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 50 additions & 18 deletions src/cm160.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
#include <usb.h>
Expand Down Expand Up @@ -54,7 +56,7 @@ static char WAIT_MSG[11] = {
#define UART_ENABLE 0x0001
#define UART_DISABLE 0x0000

struct cm160_device g_devices[MAX_DEVICES];
struct cm160_device g_devices[];
static unsigned char history[HISTORY_SIZE][11];

static void process_live_data(struct record_data *rec)
Expand All @@ -70,8 +72,9 @@ static void process_live_data(struct record_data *rec)
}
else
_watts = w;

FILE *fp = fopen(".live", "w");
char filename[255];
sprintf(filename,".%d.live",rec->addr);
FILE *fp = fopen(filename, "w");
if(fp && rec->hour!=255) // to avoid writing strange values (i.e. date 2255, hour 255:255) that sometimes I got
{
fprintf(fp, "%02d/%02d/%04d %02d:%02d - %.02f kW\n",
Expand All @@ -83,7 +86,7 @@ static void process_live_data(struct record_data *rec)
static void decode_frame(unsigned char *frame, struct record_data *rec)
{
int volt = 230; // TODO: use the value from energy_param table (supply_voltage)
rec->addr = 0; // TODO: don't use an harcoded addr value for the device...
rec->addr = g_devices[0].serial_no;
rec->year = frame[1]+2000;
rec->month = frame[2];
rec->day = frame[3];
Expand Down Expand Up @@ -314,31 +317,60 @@ static int handle_device(int dev_id)

int main(int argc, char **argv)
{
int opt = 0;
char serial[255]="";
char *serialPtr;
int index;
serialPtr = serial;
int dev_cnt;
if(argc>1 && (strcmp(argv[1], "-d")==0) )
demonize(argv[0]);

while(1)
{
while ((opt = getopt(argc,argv, "ds:")) != -1) {
switch(opt) {
case 's':
strcpy(serialPtr,optarg);
break;
case 'd':
demonize(argv[0]);
break;
case '?':
if (optopt == 's') {
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
} else if (isprint(optopt)) {
fprintf(stderr, "Unknown option '-%c'.\n", optopt);
} else {
printf("\nUnknown option character '\\x%x'.\n:", optopt);
}
break;
default:
abort();
}
}
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);

while(1) {
db_open();
dev_cnt = 0;
receive_history = true;
frame_id = 0;
printf("Wait for cm160 device to be connected\n");
while((dev_cnt = scan_usb()) == 0)
while((dev_cnt = scan_usb(serialPtr)) == 0)
sleep(2);
printf("Found %d compatible device%s\n", dev_cnt, dev_cnt>1?"s":"");
if (dev_cnt>1) {
printf("Found %d compatible devices.\nUse -s <serial> option.\n", dev_cnt);
break;
} else {
printf("Found 1 compatible device.\nStarting....\n");
if(!(g_devices[0].hdev = usb_open(g_devices[0].usb_dev))) {
fprintf(stderr, "failed to open device\n");
db_close();
break;
}

// Only 1 device supported
if(!(g_devices[0].hdev = usb_open(g_devices[0].usb_dev)))
{
fprintf(stderr, "failed to open device\n");
handle_device(0);
usb_close(g_devices[0].hdev);
db_close();
break;
}
handle_device(0);
usb_close(g_devices[0].hdev);
db_close();
}

return 0;
Expand Down
3 changes: 1 addition & 2 deletions src/cm160.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@
#ifndef __CM160_H__
#define __CM160_H__

#define MAX_DEVICES 1 // Only one device supported now

struct cm160_device {
struct usb_device *usb_dev;
usb_dev_handle *hdev;
int serial_no;
int epin; // IN end point address
int epout; // OUT end point address
};
Expand Down
69 changes: 24 additions & 45 deletions src/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,6 @@ static int create_stat_db()
printf("%s doesn't exist -> create it.\n", EAGLE_OWL_STAT_DB);
sqlite3_open_v2(EAGLE_OWL_STAT_DB, &stat_db,
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, NULL);
SQL_EXEC(stat_db, CREATE_YEAR_STAT, "Create energy_year_stat table");
SQL_EXEC(stat_db, CREATE_MONTH_STAT, "Create energy_month_stat table");
SQL_EXEC(stat_db, CREATE_DAY_STAT, "Create energy_year_day table");
SQL_EXEC(stat_db, CREATE_HOUR_STAT, "Create energy_year_hour table");

return ret;
Expand All @@ -85,7 +82,7 @@ int db_open(void)

if(ret == SQLITE_OK)
{
sqlite3_create_function(db, "update_stat_db", 5, SQLITE_UTF8, NULL,
sqlite3_create_function(db, "update_stat_db", 6, SQLITE_UTF8, NULL,
&update_stat, NULL, NULL);

SQL_EXEC(db, CREATE_UPDATE_STAT_TRIGGER, "Create update_stat trigger");
Expand Down Expand Up @@ -168,7 +165,7 @@ int db_insert_hist(struct record_data *rec)
}
else if(ret != SQLITE_OK)
{
printf("db_insert_hist error: %s\n", errmsg);
printf("db_insert_hist Error: %s\n", errmsg);
sqlite3_free(errmsg);
}
}
Expand All @@ -179,56 +176,41 @@ int db_insert_hist(struct record_data *rec)

void update_stat(sqlite3_context *context, int argc, sqlite3_value **argv)
{
if(argc != 5)
if(argc != 6)
return;

int y = sqlite3_value_int(argv[0]);
int m = sqlite3_value_int(argv[1]);
int d = sqlite3_value_int(argv[2]);
int h = sqlite3_value_int(argv[3]);
double kwh = sqlite3_value_double(argv[4]);
int addr = sqlite3_value_int(argv[0]);
int y = sqlite3_value_int(argv[1]);
int m = sqlite3_value_int(argv[2]);
int d = sqlite3_value_int(argv[3]);
int h = sqlite3_value_int(argv[4]);
double kwh = sqlite3_value_double(argv[5]);
// printf("update_stat callback called %d/%d/%d @%dh: %f kwh\n", y, m, d, h, kwh);
update_stat_db(y, m, d, h, kwh);
update_stat_db(addr, y, m, d, h, kwh);
}

int update_stat_db(int y, int m, int d, int h, double kwh)
int dayofweek(int y, int m, int d) { /* 0 = Sunday */
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}

int update_stat_db(int addr, int y, int m, int d, int h, double kwh)
{
int addr = 0; // TODO
char sql[512];
double day_conso = 0;
double night_conso = 0;

char sql[2048];
int i = 0;
int dow;
if(!db || !stat_db)
{
fprintf(stderr, "Error: db_insert_hist dbs not opened!\n");
return -1;
}

if(get_day_of_week(y, m, d) < 5 && is_full_tariff(h)) // TODO: use tariffs from db
day_conso += kwh;
else
night_conso += kwh;

// update energy_hour_stat
sprintf(sql, UPDATE_STAT_HOUR, kwh, day_conso, night_conso, y, m, d, h,
addr, y, m, d, h, kwh, day_conso, night_conso);
dow = dayofweek(y,m,d);
// update energy_hour_stat
sprintf(sql, UPDATE_STAT_HOUR, kwh, y, m, d, h, addr,
addr, y, m, d, h, dow, kwh);
SQL_EXEC(stat_db, sql, "Update stat_hour DB");

// update energy_day_stat
sprintf(sql, UPDATE_STAT_DAY, kwh, day_conso, night_conso, y, m, d,
addr, y, m, d, kwh, day_conso, night_conso);
SQL_EXEC(stat_db, sql, "Update stat_day DB");

// update energy_month_stat
sprintf(sql, UPDATE_STAT_MONTH, kwh, day_conso, night_conso, y, m,
addr, y, m, kwh, day_conso, night_conso);
SQL_EXEC(stat_db, sql, "Update stat_month DB");

// update energy_year_stat
sprintf(sql, UPDATE_STAT_YEAR, kwh, day_conso, night_conso, y,
addr, y, kwh, day_conso, night_conso);
SQL_EXEC(stat_db, sql, "Update stat_year DB");

return SQLITE_OK;
}

Expand All @@ -250,9 +232,6 @@ int db_update_status(void)
sprintf(sql, "UPDATE energy_hour_stat SET status = 1 WHERE record_count = %d", 60);
SQL_EXEC(stat_db, sql, "Update energy_hour_stat status");

sprintf(sql, "UPDATE energy_day_stat SET status = 1 WHERE record_count = %d", 60*24);
SQL_EXEC(stat_db, sql, "Update energy_day_stat status");

return SQLITE_OK;
}

2 changes: 1 addition & 1 deletion src/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ int db_insert_hist(struct record_data *rec);
int db_update_status(void);

void update_stat(sqlite3_context *context, int argc, sqlite3_value **argv);
int update_stat_db(int y, int m, int d, int h, double kwh);
int update_stat_db(int addr, int y, int m, int d, int h, double kwh);

#endif // __DB_H__
75 changes: 13 additions & 62 deletions src/sql_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,40 +64,22 @@

#define CREATE_UPDATE_STAT_TRIGGER "CREATE TRIGGER IF NOT EXISTS updatestat_cb "\
"AFTER INSERT ON energy_history" \
" BEGIN SELECT update_stat_db(NEW.year," \
" BEGIN SELECT update_stat_db(NEW.addr, NEW.year," \
" NEW.month, NEW.day, NEW.hour," \
" NEW.ch1_kw_avg/1000);" \
" END;"

#define DELETE_UPDATE_STAT_TRIGGER "DROP TRIGGER IF EXISTS updatestat_cb;"

// record_count: number of minutes records that have been used to compute the stat
// e.g: for a full day_stat: record_count should be 24*60 (24 hours of 60 minutes)
// e.g: for a full hour_stat: record_count should be 60 (60 minutes)
// status: 0: the stat is complete (record_count is the max value)
// 1: the stat is incomplete (record_count is lower than the max value)

#define CREATE_YEAR_STAT "CREATE TABLE energy_year_stat(" \
"addr INT, year INT, kwh_total INT," \
" kwh_week_total INT, kwh_weekend_total INT," \
" record_count INT, status INT," \
" PRIMARY KEY(addr, year));"

#define CREATE_MONTH_STAT "CREATE TABLE energy_month_stat(" \
"addr INT, year INT, month INT, kwh_total INT,"\
" kwh_week_total INT, kwh_weekend_total INT," \
" record_count INT, status INT," \
" PRIMARY KEY(addr, year, month));"

#define CREATE_DAY_STAT "CREATE TABLE energy_day_stat(" \
"addr INT, year INT, month INT, day INT, " \
"kwh_total INT, kwh_week_total INT, " \
"kwh_weekend_total INT, record_count INT, status INT, " \
" PRIMARY KEY(addr, year, month, day));"

#define CREATE_HOUR_STAT "CREATE TABLE energy_hour_stat(" \
"addr INT, year INT, month INT, day INT, hour INT, " \
"kwh_total INT, kwh_week_total INT, " \
"kwh_weekend_total INT, record_count INT, status INT, " \
#define CREATE_HOUR_STAT "CREATE TABLE energy_hour_stat(" \
"addr INT, year INT, month INT, day INT," \
" hour INT, dow INT, kwh_total INT," \
" record_count INT, status INT," \
" PRIMARY KEY(addr, year, month, day, hour));"

#define ATTACH_IMPORT_DB "ATTACH DATABASE '%s' AS import_db"
Expand Down Expand Up @@ -153,44 +135,13 @@
" VALUES (%d, %d, %d, %d, %d, %d," \
" %f, %f, %d, %d, %f, %f, %f, %f);"

#define UPDATE_STAT_HOUR "INSERT OR REPLACE INTO energy_hour_stat" \
" SELECT addr, year, month, day, hour, kwh_total + %f," \
" kwh_week_total + %f, kwh_weekend_total + %f," \
" record_count + 1 AS c, status FROM energy_hour_stat" \
" WHERE year=%d AND month=%d AND day=%d AND hour=%d" \
" UNION " \
" SELECT %d, %d, %d, %d, %d, %f, %f, %f, 1 as r, 0" \
" ORDER BY r DESC" \
" LIMIT 1;"

#define UPDATE_STAT_DAY "INSERT OR REPLACE INTO energy_day_stat" \
" SELECT addr, year, month, day, kwh_total + %f," \
" kwh_week_total + %f, kwh_weekend_total + %f," \
" record_count + 1 AS c, status FROM energy_day_stat" \
" WHERE year = %d AND month = %d AND day = %d" \
" UNION " \
" SELECT %d, %d, %d, %d, %f, %f, %f, 1 as r, 0" \
" ORDER BY r DESC" \
" LIMIT 1;"

#define UPDATE_STAT_MONTH "INSERT OR REPLACE INTO energy_month_stat" \
" SELECT addr, year, month, kwh_total + %f," \
" kwh_week_total + %f, kwh_weekend_total + %f," \
" record_count + 1 AS c, status FROM energy_month_stat"\
" WHERE year = %d AND month = %d" \
" UNION " \
" SELECT %d, %d, %d, %f, %f, %f, 1 as r, 0" \
" ORDER BY r DESC" \
" LIMIT 1;"

#define UPDATE_STAT_YEAR "INSERT OR REPLACE INTO energy_year_stat" \
" SELECT addr, year, kwh_total + %f," \
" kwh_week_total + %f, kwh_weekend_total + %f," \
" record_count + 1 AS c, status FROM energy_year_stat" \
" WHERE year = %d" \
" UNION " \
" SELECT %d, %d, %f, %f, %f, 1 as r, 0" \
" ORDER BY r DESC" \
#define UPDATE_STAT_HOUR "INSERT OR REPLACE INTO energy_hour_stat" \
" SELECT addr, year, month, day, hour, dow, kwh_total + %f," \
" record_count + 1 AS c, status FROM energy_hour_stat" \
" WHERE year=%d AND month=%d AND day=%d AND hour=%d AND addr=%d"\
" UNION " \
" SELECT %d, %d, %d, %d, %d, %d, %f, 1 as r, 0" \
" ORDER BY r DESC" \
" LIMIT 1;"

#endif//__EAGLEOWL_SQL_H__
Loading