Adding browse features for telemetry viewer. Updates to telemetry logging

This commit is contained in:
Paul Dino Jones 2023-07-17 16:38:34 +00:00
parent 0b3ff679a5
commit e240b7fedf
6 changed files with 1168 additions and 83 deletions

View File

@ -0,0 +1,865 @@
#include <stdbool.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ncurses.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <MQTTClient.h>
#include <poll.h>
#include <termios.h>
#include <hoel.h>
#include <jansson.h>
#include "session.h"
#include "gameloop.h"
#include "../helper/parameters.h"
#include "../helper/confighelper.h"
#include "../helper/dirhelper.h"
#include "../simulatorapi/simapi/simapi/simdata.h"
#include "../simulatorapi/simapi/simapi/simmapper.h"
#include "../slog/slog.h"
#define DEFAULT_UPDATE_RATE 60
#define DATA_UPDATE_RATE 4
#define SESSIONS_SCREEN 1
#define STINTS_SCREEN 2
#define LAPS_SCREEN 3
char datestring[30];
WINDOW* win1;
WINDOW* win2;
WINDOW* win3;
WINDOW* win4;
int winx, winy;
int win23y, win23x;
void handle_winch(int sig)
{
endwin();
refresh();
clear();
getmaxyx(stdscr, winx, winy);
//win23y = winy/3;
//win23x = winx/3;
//win1 = newwin(winx,winy,0,0);
//win2 = newwin(win23x,win23y,1,win23y-1);
//win3 = newwin(win23x,win23y,1,win23y*2-1);
//win4 = newwin(winx-win23x-2,winy-win23y,win23x+1,win23y-1);
refresh();
}
void rectangle(int y1, int x1, int y2, int x2)
{
mvhline(y1, x1, 0, x2-x1);
mvhline(y2, x1, 0, x2-x1);
mvvline(y1, x1, 0, y2-y1);
mvvline(y1, x2, 0, y2-y1);
mvaddch(y1, x1, ACS_ULCORNER);
mvaddch(y2, x1, ACS_LLCORNER);
mvaddch(y1, x2, ACS_URCORNER);
mvaddch(y2, x2, ACS_LRCORNER);
}
int curses_init()
{
initscr();
start_color();
init_pair(1,COLOR_GREEN,0);
init_pair(2,COLOR_YELLOW,0);
init_pair(3,COLOR_MAGENTA,0);
init_pair(4,COLOR_WHITE,0);
getmaxyx(stdscr, winx, winy);
win1 = newwin(winx,winy,0,0);
//win23y = winy/3;
//win23x = winx/3;
//win2 = newwin(win23x,win23y,1,win23y-1);
//win3 = newwin(win23x,win23y,1,win23y*2-1);
//win4 = newwin(winx-win23x-2,winy-win23y,win23x+1,win23y-1);
wbkgd(win1,COLOR_PAIR(1));
wbkgd(win2,COLOR_PAIR(1));
wbkgd(win3,COLOR_PAIR(1));
wbkgd(win4,COLOR_PAIR(1));
signal(SIGWINCH, handle_winch);
cbreak();
noecho();
box(win1, 0, 0);
box(win2, 0, 0);
box(win3, 0, 0);
box(win4, 0, 0);
}
char * removeSpacesFromStr(char *string)
{
int non_space_count = 0;
for (int i = 0; string[i] != '\0'; i++)
{
if (string[i] != ' ')
{
string[non_space_count] = string[i];
non_space_count++;
}
}
string[non_space_count] = '\0';
return string;
}
void update_date()
{
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
sprintf(datestring, "%.24s", asctime (timeinfo));
}
void print_result(struct _h_result result) {
int col, row, i;
char buf[64];
slogi("rows: %d, col: %d", result.nb_rows, result.nb_columns);
for (row = 0; row<result.nb_rows; row++) {
for (col=0; col<result.nb_columns; col++) {
switch(result.data[row][col].type) {
case HOEL_COL_TYPE_INT:
printf("| %d ", ((struct _h_type_int *)result.data[row][col].t_data)->value);
break;
case HOEL_COL_TYPE_DOUBLE:
printf("| %f ", ((struct _h_type_double *)result.data[row][col].t_data)->value);
break;
case HOEL_COL_TYPE_TEXT:
printf("| %s ", ((struct _h_type_text *)result.data[row][col].t_data)->value);
break;
case HOEL_COL_TYPE_BLOB:
for (i=0; i<((struct _h_type_blob *)result.data[row][col].t_data)->length; i++) {
printf("%c", *((char*)(((struct _h_type_blob *)result.data[row][col].t_data)->value+i)));
if (i%80 == 0 && i>0) {
printf("\n");
}
}
break;
case HOEL_COL_TYPE_DATE:
strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &((struct _h_type_datetime *)result.data[row][col].t_data)->value);
printf("| %s ", buf);
case HOEL_COL_TYPE_NULL:
printf("| [null] ");
break;
}
}
printf("|\n");
}
}
void get_row_results(struct _h_result result, DBField* fields, void* rows, size_t rowsize) {
int col, row, i;
char buf[64];
//sess->hasdata = true;
//sess->rows = result.nb_rows;
slogi("rows: %d, col: %d", result.nb_rows, result.nb_columns);
char* aaa = (char *) rows;
for (row = 0; row<result.nb_rows; row++) {
char* aa = (char*)aaa + (rowsize * row);
for (col=0; col<result.nb_columns; col++) {
char* a = (char*) aa + fields[col].offset;
switch(result.data[row][col].type) {
case HOEL_COL_TYPE_INT:
int bb = ((struct _h_type_int *)result.data[row][col].t_data)->value;
*(int*) a = bb;
break;
case HOEL_COL_TYPE_DOUBLE:
double cc = ((struct _h_type_double *)result.data[row][col].t_data)->value;
*(double*) a = cc;
break;
case HOEL_COL_TYPE_TEXT:
char* ddd = ((struct _h_type_text *)result.data[row][col].t_data)->value;
memcpy(a, ddd, fields[col].size);
break;
case HOEL_COL_TYPE_BLOB:
for (i=0; i<((struct _h_type_blob *)result.data[row][col].t_data)->length; i++) {
printf("%c", *((char*)(((struct _h_type_blob *)result.data[row][col].t_data)->value+i)));
if (i%80 == 0 && i>0) {
printf("\n");
}
}
break;
case HOEL_COL_TYPE_DATE:
strftime(a, fields[col].size, "%Y-%m-%d %H:%M:%S", &((struct _h_type_datetime *)result.data[row][col].t_data)->value);
//strftime(buf, 64, "%Y-%m-%d %H:%M:%S", &((struct _h_type_datetime *)result.data[row][col].t_data)->value);
printf("| %s ", buf);
case HOEL_COL_TYPE_NULL:
printf("| [null] ");
break;
}
}
printf("|\n");
}
}
int getsessions(struct _h_connection* conn, const char* sessionname, SessionDbo* sess)
{
struct _h_result result;
struct _h_data * data;
char* query = malloc(99 * sizeof(char));
slogt("Performing query");
//sprintf(query, "select session_id, event_id, event_type, duration_min, elapsed_ms, laps, air_temp, road_temp, start_grip, current_grip, is_finished, http_port from %s", "Sessions");
sprintf(query, "select session_id, event_id, event_type, laps FROM %s", "Sessions");
if (h_query_select(conn, query, &result) == H_OK) {
sess->rows = malloc(sizeof(SessionRowData) * result.nb_rows);
get_row_results(result, sess->fields, sess->rows, sizeof(SessionRowData));
//get_session_result(result, sess);
h_clean_result(&result);
} else {
printf("Error executing query\n");
}
free(query);
return result.nb_rows;
}
int getstints(struct _h_connection* conn, const char* sessionname, StintDbo* stint, int use_id)
{
struct _h_result result;
struct _h_data * data;
char* query = malloc(150 * sizeof(char));
slogt("Performing query stints");
sprintf(query, "select stint_id, driver_id, team_member_id, session_id, car_id, game_car_id, laps, valid_laps, best_lap_id FROM %s WHERE session_id=%i", "Stints", use_id);
if (h_query_select(conn, query, &result) == H_OK) {
stint->rows = malloc(sizeof(StintRowData) * result.nb_rows);
get_row_results(result, stint->fields, stint->rows, sizeof(StintRowData));
//get_stint_result(result, stint);
h_clean_result(&result);
} else {
printf("Error executing query\n");
}
free(query);
return result.nb_rows;
}
int getlaps(struct _h_connection* conn, const char* sessionname, LapDbo* laps, int use_id)
{
struct _h_result result;
struct _h_data * data;
char* query = malloc(150 * sizeof(char));
slogt("Performing query laps");
sprintf(query, "select * FROM %s WHERE stint_id=%i", "Laps", use_id);
if (h_query_select(conn, query, &result) == H_OK) {
laps->rows = malloc(sizeof(LapRowData) * result.nb_rows);
get_row_results(result, laps->fields, laps->rows, sizeof(LapRowData));
//get_stint_result(result, stint);
h_clean_result(&result);
} else {
printf("Error executing query\n");
}
free(query);
return result.nb_rows;
}
//int getsessions(struct _h_connection* conn, const char* carname)
//{
// json_t *j_result;
// char* where_clause = h_build_where_clause(conn, "car_name=%s", carname);
// json_t* j_query = json_pack("{sss[s]s{s{ssss}}}","table", "sessions", "columns", "session_id", "session_name", "laps",
// "where", " ", "operator", "raw",
// "value", where_clause);
//
// slogi("Looking for car named %s", carname);
// //char* qq;
// int res = h_select(conn, j_query, &j_result, NULL);
// //slogi("here your query: %s", qq);
// // Deallocate j_query since it won't be needed anymore
// json_decref(j_query);
// h_free(where_clause);
// int session_id = -1;
// int sessions = 0;
// // Test query execution result
// if (res == H_OK) {
// // Print result
// char* dump = json_dumps(j_result, JSON_INDENT(2));
// slogi("json select result is\n%s", dump);
// int index1 = json_array_size(j_result);
// sessions = index1;
// if (index1 == 0)
// {
// slogw("no car by this name");
// }
// else {
// for (int k = 0; k < index1; k++)
// {
// json_t* jj = json_array_get(j_result, k);
// session_id = json_integer_value(json_object_get(jj, "session_id"));
// int laps = json_integer_value(json_object_get(jj, "laps"));
// slogt("found session %i with %i laps", session_id, laps);
// }
// }
// // Deallocate data result
// json_decref(j_result);
// free(dump);
// } else {
// sloge("Error executing select query: %d", res);
// }
// return sessions;
//}
void* browseloop(Parameters* p)
{
struct _h_result result;
struct _h_connection * conn;
char* connectionstring = "host=zorak.brak dbname=gilles user=test password=thisisatest";
conn = h_connect_pgsql(connectionstring);
slogt("Starting analyzer");
curses_init();
timeout(DEFAULT_UPDATE_RATE);
SessionDbo sess;
DBField sessid;
sessid.type = HOEL_COL_TYPE_INT;
sessid.offset = 0;
sessid.colnum = 0;
DBField laps;
laps.type = HOEL_COL_TYPE_INT;
laps.offset = sizeof(int);
laps.offset = offsetof(SessionRowData, laps);
laps.colnum = 1;
DBField eventid;
eventid.type = HOEL_COL_TYPE_INT;
eventid.offset = offsetof(SessionRowData, event_id);
DBField eventtype;
eventtype.type = HOEL_COL_TYPE_INT;
eventtype.offset = offsetof(SessionRowData, event_type);
//SessionFields sf;
sess.fields[0] = sessid;
sess.fields[1] = eventid;
sess.fields[2] = eventtype;
sess.fields[3] = laps;
//sf.session_id = sessid;
//sf.laps = laps;
//sess.fields = sf;
int action = 0;
int selection = 1;
int lastselection = 1;
int selection1 = 0;
int selection2 = 0;
int sessions = 0;
int lapsresults = 0;
int curresults = 0;
int stintsid = 0;
StintDbo stints;
DBField stintid;
stintid.type = HOEL_COL_TYPE_INT;
stintid.offset = 0;
DBField driverid;
driverid.type = HOEL_COL_TYPE_INT;
driverid.offset = offsetof(StintRowData, driver_id);
DBField teammemberid;
teammemberid.type = HOEL_COL_TYPE_INT;
teammemberid.offset = offsetof(StintRowData, team_member_id);
DBField sessionidstint;
sessionidstint.type = HOEL_COL_TYPE_INT;
sessionidstint.offset = offsetof(StintRowData, session_id);
DBField carid;
carid.type = HOEL_COL_TYPE_INT;
carid.offset = offsetof(StintRowData, car_id);
DBField gamecarid;
gamecarid.type = HOEL_COL_TYPE_INT;
gamecarid.offset = offsetof(StintRowData, game_car_id);
DBField stintlaps;
stintlaps.type = HOEL_COL_TYPE_INT;
stintlaps.offset = offsetof(StintRowData, laps);
DBField validlaps;
validlaps.type = HOEL_COL_TYPE_INT;
validlaps.offset = offsetof(StintRowData, valid_laps);
DBField bestlapid;
bestlapid.type = HOEL_COL_TYPE_INT;
bestlapid.offset = offsetof(StintRowData, best_lap_id);
stints.fields[0] = stintid;
stints.fields[1] = driverid;
stints.fields[2] = teammemberid;
stints.fields[3] = sessionidstint;
stints.fields[4] = carid;
stints.fields[5] = gamecarid;
stints.fields[6] = stintlaps;
stints.fields[7] = validlaps;
stints.fields[8] = bestlapid;
LapDbo lapsdb;
DBField lapsdbid;
lapsdbid.type = HOEL_COL_TYPE_INT;
lapsdbid.offset = 0;
DBField lapsdbstintid;
lapsdbstintid.type = HOEL_COL_TYPE_INT;
lapsdbstintid.offset = offsetof(LapRowData, stint_id);
DBField sector_1;
sector_1.type = HOEL_COL_TYPE_INT;
sector_1.offset = offsetof(LapRowData, sector_1);
DBField sector_2;
sector_2.type = HOEL_COL_TYPE_INT;
sector_2.offset = offsetof(LapRowData, sector_2);
DBField sector_3;
sector_3.type = HOEL_COL_TYPE_INT;
sector_3.offset = offsetof(LapRowData, sector_3);
DBField grip;
grip.type = HOEL_COL_TYPE_DOUBLE;
grip.offset = offsetof(LapRowData, grip);
DBField tyrec;
tyrec.type = HOEL_COL_TYPE_TEXT;
tyrec.offset = offsetof(LapRowData, tyre);
tyrec.size = sizeof(unsigned char)*10;
DBField time;
time.type = HOEL_COL_TYPE_INT;
time.offset = offsetof(LapRowData, time);
DBField cuts;
cuts.type = HOEL_COL_TYPE_INT;
cuts.offset = offsetof(LapRowData, cuts);
DBField carcrashes;
carcrashes.type = HOEL_COL_TYPE_INT;
carcrashes.offset = offsetof(LapRowData, crashes);
DBField maxspeed;
maxspeed.type = HOEL_COL_TYPE_INT;
maxspeed.offset = offsetof(LapRowData, max_speed);
DBField avgspeed;
avgspeed.type = HOEL_COL_TYPE_INT;
avgspeed.offset = offsetof(LapRowData, avg_speed);
DBField lapsdbfinishedat;
lapsdbfinishedat.type = HOEL_COL_TYPE_DATE;
lapsdbfinishedat.offset = offsetof(LapRowData, finished_at);
lapsdbfinishedat.size = sizeof(PDBTimeStamp);
lapsdb.fields[0] = lapsdbid;
lapsdb.fields[1] = lapsdbstintid;
lapsdb.fields[2] = sector_1;
lapsdb.fields[3] = sector_2;
lapsdb.fields[4] = sector_3;
lapsdb.fields[5] = grip;
lapsdb.fields[6] = tyrec;
lapsdb.fields[7] = time;
lapsdb.fields[8] = cuts;
lapsdb.fields[9] = carcrashes;
lapsdb.fields[10] = maxspeed;
lapsdb.fields[11] = avgspeed;
lapsdb.fields[12] = lapsdbfinishedat;
//slogt("sessions has %i rows", sess.numrows);
action = 2;
int go = true;
char lastsimstatus = false;
int screen = SESSIONS_SCREEN;
char ch;
box(win1, 0, 0);
wrefresh(win1);
int useid = 0;
while (go == true)
{
if (lastselection != selection)
{
action = 1;
lastselection = selection;
}
if (action == 2)
{
slogt("going to perform an action");
sessions = getsessions(conn, "Sessions", &sess);
curresults = sessions;
}
if (action == 3)
{
slogt("going to perform an action");
stintsid = getstints(conn, "Stints", &stints, useid);
curresults = stintsid;
}
if (action == 4)
{
slogt("going to perform an action");
lapsresults = getlaps(conn, "laps", &lapsdb, useid);
curresults = lapsresults;
}
if (action > 0)
{
wclear(win1);
wprintw(win1, "\n");
switch(screen) {
case SESSIONS_SCREEN:
for(int i=0; i<sessions+1; i++)
{
if (i == 0)
{
char spacer[4];
sprintf(spacer, "\n");
waddstr(win1, spacer);
char selectind[4];
char clastlap[26];
sprintf(clastlap, " session name ");
waddstr(win1, clastlap);
wprintw(win1, " ");
char cbestlap[14];
sprintf(cbestlap, " laps ");
waddstr(win1, cbestlap);
wprintw(win1, "\n");
}
else
{
char spacer[4];
sprintf(spacer, "\n");
waddstr(win1, spacer);
char selectind[6];
if ( i == selection )
{
useid = sess.rows[i-1].session_id;
sprintf(selectind, "_*_");
waddstr(win1, selectind);
}
else
{
sprintf(selectind, "___");
waddstr(win1, selectind);
}
int maxstrlen = 20;
wprintw(win1, " %i ", sess.rows[i-1].session_id);
char clastlap[14];
sprintf(clastlap, "session name");
waddstr(win1, clastlap);
wprintw(win1, " ");
char cbestlap[14];
sprintf(cbestlap, "laps %i", sess.rows[i-1].laps);
waddstr(win1, cbestlap);
wprintw(win1, "\n");
}
//box(win1, 0, 0);
//wrefresh(win1);
}
break;
case STINTS_SCREEN:
if (stintsid == 0)
{
break;
}
for(int i=0; i<stintsid+1; i++)
{
if (i == 0)
{
char spacer[4];
sprintf(spacer, "\n");
waddstr(win1, spacer);
char selectind[4];
char clastlap[26];
sprintf(clastlap, " stint name ");
waddstr(win1, clastlap);
wprintw(win1, " ");
char cbestlap[14];
sprintf(cbestlap, " laps ");
waddstr(win1, cbestlap);
wprintw(win1, "\n");
}
else
{
char spacer[4];
sprintf(spacer, "\n");
waddstr(win1, spacer);
char selectind[4];
if ( i == selection )
{
sprintf(selectind, "_*_");
waddstr(win1, selectind);
useid = stints.rows[i-i].stint_id;
}
else
{
sprintf(selectind, "___");
waddstr(win1, selectind);
}
int maxstrlen = 20;
wprintw(win1, " %i ", stints.rows[i-1].stint_id);
char clastlap[14];
sprintf(clastlap, "stint name");
waddstr(win1, clastlap);
wprintw(win1, " ");
char cbestlap[14];
sprintf(cbestlap, "laps %i", stints.rows[i-1].driver_id);
waddstr(win1, cbestlap);
wprintw(win1, "\n");
}
}
break;
//wattrset(win4, COLOR_PAIR(1));
case LAPS_SCREEN:
if (lapsresults == 0)
{
break;
}
for(int i=0; i<lapsresults+1; i++)
{
if (i == 0)
{
char spacer[4];
sprintf(spacer, "\n");
waddstr(win1, spacer);
char selectind[4];
char clastlap[16];
sprintf(clastlap, " lap name ");
waddstr(win1, clastlap);
wprintw(win1, " ");
char cbestlap[14];
sprintf(cbestlap, " tyre ");
waddstr(win1, cbestlap);
wprintw(win1, "\n");
}
else
{
char spacer[4];
sprintf(spacer, "\n");
waddstr(win1, spacer);
char selectind[4];
if ( i == selection )
{
sprintf(selectind, "_*_");
waddstr(win1, selectind);
}
else
{
sprintf(selectind, "___");
waddstr(win1, selectind);
}
char selectind1[4];
if ( i == selection1 )
{
sprintf(selectind1, "_1_");
waddstr(win1, selectind1);
}
else if ( i == selection2 )
{
sprintf(selectind1, "_2_");
waddstr(win1, selectind1);
}
else
{
sprintf(selectind1, "___");
waddstr(win1, selectind1);
}
int maxstrlen = 20;
wprintw(win1, " %i ", lapsdb.rows[i-1].lap_id);
char clastlap[14];
sprintf(clastlap, "lap name");
waddstr(win1, clastlap);
wprintw(win1, " ");
char cbestlap[14];
sprintf(cbestlap, "laps %i", lapsdb.rows[i-1].max_speed);
waddstr(win1, cbestlap);
wprintw(win1, " ");
char gripstr[14];
sprintf(gripstr, "%s", lapsdb.rows[i-1].tyre);
waddstr(win1, gripstr);
wprintw(win1, " ");
char finstr[30];
sprintf(finstr, " %s ", lapsdb.rows[i-1].finished_at);
waddstr(win1, finstr);
wprintw(win1, "\n");
}
}
break;
//wattrset(win4, COLOR_PAIR(1));
}
action = 0;
}
box(win1, 0, 0);
//box(win2, 0, 0);
//box(win3, 0, 0);
//box(win4, 0, 0);
wrefresh(win1);
//wrefresh(win2);
//wrefresh(win3);
//wrefresh(win4);
scanf("%c", &ch);
if(ch == 'q')
{
go = false;
}
if (ch == 'b')
{
switch(screen) {
case STINTS_SCREEN:
action = 2;
screen = SESSIONS_SCREEN;
break;
case LAPS_SCREEN:
action = 3;
screen = STINTS_SCREEN;
break;
}
selection = 1;
lastselection = 1;
}
if (ch == 'e')
{
switch(screen) {
case SESSIONS_SCREEN:
action = 3;
screen = STINTS_SCREEN;
break;
case STINTS_SCREEN:
action = 4;
screen = LAPS_SCREEN;
break;
}
selection = 1;
lastselection = 1;
}
if (ch == 'B')
{
selection++;
if (selection > curresults)
{
selection = curresults;
}
}
if (ch == 'A')
{
selection--;
if (selection <= 1)
{
selection = 1;
}
}
if (ch == '1')
{
selection1 = selection;
action = 1;
}
if (ch == '2')
{
selection2 = selection;
action = 1;
}
}
wrefresh(win4);
delwin(win4);
endwin();
wrefresh(win3);
delwin(win3);
endwin();
wrefresh(win2);
delwin(win2);
endwin();
wrefresh(win1);
delwin(win1);
endwin();
h_close_db(conn);
h_clean_connection(conn);
//return 0;
}

View File

@ -0,0 +1,4 @@
#include "../helper/parameters.h"
#include "../helper/confighelper.h"
int browseloop(Parameters* p);

View File

@ -166,25 +166,10 @@ int mainloop(Parameters* p)
getSim(simdata, simmap, &p->simon, &p->sim);
// check for running sims
if (file_exists("/dev/shm/acpmf_physics"))
{
if (file_exists("/dev/shm/acpmf_static"))
{
p->sim = SIMULATOR_ASSETTO_CORSA;
int error = siminit(simdata, simmap, 1);
simdatamap(simdata, simmap, 1);
if (error == 0 && simdata->simstatus > 1)
{
slogi("found Assetto Corsa, starting application...");
p->simon = true;
}
}
}
if (p->simon == true) if (p->simon == true) {
{
if (p->cli == true) if (p->cli == true)
{ {
if (pthread_create(&ui_thread, NULL, &clilooper, p) != 0) if (pthread_create(&ui_thread, NULL, &clilooper, p) != 0)
@ -824,8 +809,7 @@ int addsession(struct _h_connection* conn, int eventid, int eventtype, int airte
// session_id | event_id | event_type | track_time | session_name // session_id | event_id | event_type | track_time | session_name
// | start_time | duration_min | elapsed_ms | laps | weather | // | start_time | duration_min | elapsed_ms | laps | weather |
// air_temp | road_temp | start_grip | current_grip | is_finished // air_temp | road_temp | start_grip |
// | finish_time | last_activity | http_port
json_t *root = json_object(); json_t *root = json_object();
json_t *json_arr = json_array(); json_t *json_arr = json_array();
@ -836,11 +820,12 @@ int addsession(struct _h_connection* conn, int eventid, int eventtype, int airte
json_object_set_new(values, "event_id", json_integer(eventid)); json_object_set_new(values, "event_id", json_integer(eventid));
json_object_set_new(values, "event_type", json_integer(1)); json_object_set_new(values, "event_type", json_integer(1));
json_object_set_new(values, "duration_min", json_integer(60)); json_object_set_new(values, "duration_min", json_integer(60));
json_object_set_new(values, "start_time", json_string("NOW()"));
json_object_set_new(values, "session_name", json_string("default")); json_object_set_new(values, "session_name", json_string("default"));
json_object_set_new(values, "last_activity", json_string("2023-06-27"));
json_object_set_new(values, "air_temp", json_integer(airtemp)); json_object_set_new(values, "air_temp", json_integer(airtemp));
json_object_set_new(values, "road_temp", json_integer(tracktemp)); json_object_set_new(values, "road_temp", json_integer(tracktemp));
json_object_set_new(values, "weather", json_string("Windy")); json_object_set_new(values, "weather", json_string("Windy"));
json_object_set_new(values, "http_port", json_integer(0));
json_array_append(json_arr, values); json_array_append(json_arr, values);
int res = h_insert(conn, root, NULL); int res = h_insert(conn, root, NULL);
slogt("session insert response: %i", res); slogt("session insert response: %i", res);
@ -852,8 +837,7 @@ int addsession(struct _h_connection* conn, int eventid, int eventtype, int airte
int addstint(struct _h_connection* conn, int sessionid, int driverid, int carid) int addstint(struct _h_connection* conn, int sessionid, int driverid, int carid)
{ {
// stints
// session_stint_id | driver_id | team_member_id | session_id | car_id | game_car_id | laps | valid_laps | best_lap_id | is_finished | started_at | finished_at
json_t *root = json_object(); json_t *root = json_object();
json_t *json_arr = json_array(); json_t *json_arr = json_array();
@ -863,10 +847,16 @@ int addstint(struct _h_connection* conn, int sessionid, int driverid, int carid)
json_t* values = json_object(); json_t* values = json_object();
json_object_set_new(values, "driver_id", json_integer(driverid)); json_object_set_new(values, "driver_id", json_integer(driverid));
//team_member_id
json_object_set_new(values, "session_id", json_integer(sessionid)); json_object_set_new(values, "session_id", json_integer(sessionid));
json_object_set_new(values, "car_id", json_integer(carid)); json_object_set_new(values, "car_id", json_integer(carid));
json_object_set_new(values, "game_car_id", json_integer(carid)); json_object_set_new(values, "game_car_id", json_integer(carid));
json_object_set_new(values, "started_at", json_string("2023-06-25") ); json_object_set_new(values, "laps", json_integer(0));
json_object_set_new(values, "valid_laps", json_integer(0));
// best_lap_id
json_object_set_new(values, "is_finished", json_integer(0));
json_object_set_new(values, "started_at", json_string("NOW()") );
json_array_append(json_arr, values); json_array_append(json_arr, values);
int res = h_insert(conn, root, NULL); int res = h_insert(conn, root, NULL);
slogt("stint insert response: %i", res); slogt("stint insert response: %i", res);
@ -875,11 +865,65 @@ int addstint(struct _h_connection* conn, int sessionid, int driverid, int carid)
return getLastInsertID(conn); return getLastInsertID(conn);
} }
int closesession(struct _h_connection* conn, int sessionid)
{
// best_lap_id
// session_id | event_id | event_type | track_time | session_name
// | start_time | duration_min | elapsed_ms | laps | weather |
// air_temp | road_temp | start_grip | end_grip | is_finished
char* query = malloc((sizeof(char)*71));
sprintf(query, "UPDATE sessions SET is_finished=1, finished_at=NOW() WHERE sessionid=%i", "sessions", sessionid);
int res1 = h_query_update(conn, query);
free(query);
return res1;
}
int closestint(struct _h_connection* conn, int stintid, int stintlaps, int validstintlaps)
{
// best_lap_id
char* query = malloc((sizeof(char)*71));
sprintf(query, "UPDATE stints SET %s = %i, %s = %i, is_finished=1, finished_at=NOW() WHERE stintid=%i", "laps", stintlaps, "valid_laps", validstintlaps, stintid);
int res1 = h_query_update(conn, query);
free(query);
return res1;
}
int closelap(struct _h_connection* conn, int lapid, int sector1, int sector2, int sector3, int cuts, int crashes, int maxspeed, int avgspeed,
int fbraketemp, int rbraketemp, int ftyrewear, int rtyrewear, int ftyretemp, int rtyretemp, int ftyrepress, int rtyrepress)
{
// stint laps
// lap_id | stint_id | sector_1 | sector_2 | sector_3 | grip | tyre | time | cuts | crashes
// max_speed | avg_speed | finished_at
char* query = malloc((sizeof(char)*171));
sprintf(query, "UPDATE laps SET %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, %s=%f, finished_at=NOW() WHERE lapid=%i",
"laps", "front_tyre_temp", ftyretemp, "rear_tyre_temp", rtyretemp, "front_tyre_wear", ftyrewear, "rear_tyre_wear", rtyrewear,
"front_tyre_press", ftyrepress, "rear_tyre_press", rtyrepress, "front_brake_temp", fbraketemp, "rear_brake_temp", rbraketemp, lapid);
int res1 = h_query_update(conn, query);
free(query);
return res1;
}
int addstintlap(struct _h_connection* conn, int stintid) int addstintlap(struct _h_connection* conn, int stintid)
{ {
// stint laps // stint laps
// stint_lap_id | stint_id | sector_1 | sector_2 | sector_3 | grip | tyre | time | cuts | crashes | car_crashes | max_speed | avg_speed | finished_at // stint_lap_id | stint_id | sector_1 | sector_2 | sector_3 | grip | tyre | time | cuts | crashes
// max_speed | avg_speed | finished_at
json_t *root = json_object(); json_t *root = json_object();
json_t *json_arr = json_array(); json_t *json_arr = json_array();
@ -961,39 +1005,12 @@ int updatetelemetry(struct _h_connection* conn, int telemid, int size, const cha
//snprintf(pp, (size*2)+1, "%s%02hhX", pp, p[i]); //snprintf(pp, (size*2)+1, "%s%02hhX", pp, p[i]);
} }
//char output2[((size*2)+3)];
////snprintf(output2, (size*2)+18, "%s%s%s", "decode('", output, "', 'hex')");
//snprintf(output2, (size*2)+18, "%s %s%s", "decode('", output, "', 'hex')");
//slogt("heres a string %s", output2);
//json_t* j_query = json_pack("{sss[{siso}]}",
// "table",
// "lap_telemetry",
// "values",
// "lap_id",
// lapid,
// "steer",
// json_pack("s", "decode('deadbeef', 'hex')"));
char* query = malloc((sizeof(char)*71)+(sizeof(column))+(size*2)+1); char* query = malloc((sizeof(char)*71)+(sizeof(column))+(size*2)+1);
sprintf(query, "UPDATE telemetry SET %s = decode('%s', 'hex') WHERE telemetry_id = %i", column, &output, telemid); sprintf(query, "UPDATE telemetry SET %s = decode('%s', 'hex') WHERE telemetry_id = %i", column, &output, telemid);
int res1 = h_query_update(conn, query); int res1 = h_query_update(conn, query);
//int res1 = h_insert(conn, j_query, NULL); //int res1 = h_insert(conn, j_query, NULL);
slogt("got res %i", res1); slogt("got res %i", res1);
free(query); free(query);
//json_t *root = json_object();
//json_t *json_arr = json_array();
//json_object_set_new( root, "table", json_string("lap_telemetry") );
//json_object_set_new( root, "values", json_arr );
//json_t* values = json_object();
//json_object_set_new(values, "lap_id", json_integer(lapid));
//json_object_set_new(values, "steer", json_string(output2));
//json_array_append(json_arr, values);
//int res = h_insert(conn, root, NULL);
//json_decref(root);
//json_decref(values);
return res1; return res1;
} }
@ -1152,17 +1169,6 @@ void* simviewmysql(void* thargs)
carid = addcar(conn, carid, simdata->car); carid = addcar(conn, carid, simdata->car);
// ?? close last session // ?? close last session
// sessions
// session_id | event_id | event_type | track_time | session_name | start_time | duration_min | elapsed_ms | laps | weather | air_temp | road_temp | start_grip | current_grip | is_finished | finish_time | last_activity | http_port
// stints
// session_stint_id | driver_id | team_member_id | session_id | car_id | game_car_id | laps | valid_laps | best_lap_id | is_finished | started_at | finished_at
// stint laps
// stint_lap_id | stint_id | sector_1 | sector_2 | sector_3 | grip | tyre | time | cuts | crashes | car_crashes | max_speed | avg_speed | finished_at
// telemetry
// lap_id | telemetry
int pitstatus = 0; int pitstatus = 0;
int sessionstatus = 0; int sessionstatus = 0;
@ -1188,16 +1194,32 @@ void* simviewmysql(void* thargs)
int tick = 0; int tick = 0;
slogt("spline %f", simdata->trackspline);
int track_samples = simdata->trackspline / TRACK_SAMPLE_RATE; int track_samples = simdata->trackspline / TRACK_SAMPLE_RATE;
slogt("track samples %i", track_samples); slogt("track samples %i", track_samples);
int stintlaps = 0;
int validstintlaps = 0;
bool validind = true;
int* speeddata = malloc(track_samples * sizeof(simdata->velocity)); int* speeddata = malloc(track_samples * sizeof(simdata->velocity));
int* rpmdata = malloc(track_samples * sizeof(simdata->rpms));
int* geardata = malloc(track_samples * sizeof(simdata->gear));
double* steerdata = malloc(track_samples * sizeof(simdata->steer)); double* steerdata = malloc(track_samples * sizeof(simdata->steer));
double* acceldata = malloc(track_samples * sizeof(simdata->gas)); double* acceldata = malloc(track_samples * sizeof(simdata->gas));
double* brakedata = malloc(track_samples * sizeof(simdata->brake)); double* brakedata = malloc(track_samples * sizeof(simdata->brake));
//double* tyretemp0 = malloc(track_samples * sizeof(simdata->tyretemp[0]));
//double* tyretemp1 = malloc(track_samples * sizeof(simdata->tyretemp[0]));
//double* tyretemp2 = malloc(track_samples * sizeof(simdata->tyretemp[0]));
//double* tyretemp3 = malloc(track_samples * sizeof(simdata->tyretemp[0]));
//double* tyrepressure0 = malloc(track_samples * sizeof(simdata->tyrepressure[0]));
//double* tyrepressure1 = malloc(track_samples * sizeof(simdata->tyrepressure[0]));
//double* tyrepressure2 = malloc(track_samples * sizeof(simdata->tyrepressure[0]));
//double* tyrepressure3 = malloc(track_samples * sizeof(simdata->tyrepressure[0]));
//double* braketemp0 = malloc(track_samples * sizeof(simdata->braketemp[0]));
//double* braketemp1 = malloc(track_samples * sizeof(simdata->braketemp[0]));
//double* braketemp2 = malloc(track_samples * sizeof(simdata->braketemp[0]));
//double* braketemp3 = malloc(track_samples * sizeof(simdata->braketemp[0]));
while (go == true && p->program_state >= 0) while (go == true && p->program_state >= 0)
{ {
@ -1208,9 +1230,31 @@ void* simviewmysql(void* thargs)
slogt("normpos %i", pos); slogt("normpos %i", pos);
steerdata[pos] = simdata->steer; steerdata[pos] = simdata->steer;
acceldata[pos] = simdata->gas; acceldata[pos] = simdata->gas;
speeddata[pos] = simdata->velocity;
brakedata[pos] = simdata->brake; brakedata[pos] = simdata->brake;
speeddata[pos] = simdata->velocity;
rpmdata[pos] = simdata->rpms;
geardata[pos] = simdata->gear;
//tyretemp0[pos] = simdata->tyretemp[0];
//tyretemp1[pos] = simdata->tyretemp[1];
//tyretemp2[pos] = simdata->tyretemp[2];
//tyretemp3[pos] = simdata->tyretemp[3];
//tyrepressure0[pos] = simdata->tyrepressure[0];
//tyrepressure1[pos] = simdata->tyrepressure[1];
//tyrepressure2[pos] = simdata->tyrepressure[2];
//tyrepressure3[pos] = simdata->tyrepressure[3];
//braketemp0[pos] = simdata->braketemp[0];
//braketemp1[pos] = simdata->braketemp[1];
//braketemp2[pos] = simdata->braketemp[2];
//braketemp3[pos] = simdata->braketemp[3];
if (!simdata->lapisvalid)
{
validind = false;
}
pitstatus = 0; pitstatus = 0;
sessionstatus = simdata->session; sessionstatus = simdata->session;
lap = simdata->lap; lap = simdata->lap;
@ -1218,6 +1262,7 @@ void* simviewmysql(void* thargs)
{ {
sessionid = addsession(conn, eventid, simdata->session, simdata->airtemp, simdata->tracktemp); sessionid = addsession(conn, eventid, simdata->session, simdata->airtemp, simdata->tracktemp);
pitstatus = 1; pitstatus = 1;
stintlaps = 0;
} }
if (simdata->inpit == true) if (simdata->inpit == true)
{ {
@ -1226,21 +1271,38 @@ void* simviewmysql(void* thargs)
if (pitstatus = 0 && pitstatus != lastpitstatus) if (pitstatus = 0 && pitstatus != lastpitstatus)
{ {
// close last stint // close last stint
closestint(conn, stintid, stintlaps, validstintlaps);
stintid = addstint(conn, sessionid, driverid, carid); stintid = addstint(conn, sessionid, driverid, carid);
stintlaps = 0;
} }
if (lap != lastlap) if (lap != lastlap)
{ {
stintlaps++;
if (validind == true)
{
validstintlaps++;
}
double fbraketemp = (simdata->braketemp[0] + simdata->braketemp[1])/2;
double rbraketemp = (simdata->braketemp[2] + simdata->braketemp[3])/2;
double ftyrewear = (simdata->tyrewear[0] + simdata->tyrewear[1])/2;
double rtyrewear = (simdata->tyrewear[2] + simdata->tyrewear[3])/2;
double ftyretemp = (simdata->tyretemp[0] + simdata->tyretemp[1])/2;
double rtyretemp = (simdata->tyretemp[2] + simdata->tyretemp[3])/2;
double ftyrepress = (simdata->tyrepressure[0] + simdata->tyrepressure[1])/2;
double rtyrepress = (simdata->tyrepressure[2] + simdata->tyrepressure[3])/2;
closelap(conn, stintlapid, 0, 0, 0, 0, 0, 0, 0, fbraketemp, rbraketemp, ftyrewear, rtyrewear, ftyretemp, rtyretemp, ftyrepress, rtyrepress);
slogt("New lap detected"); slogt("New lap detected");
stintlapid = addstintlap(conn, stintid); stintlapid = addstintlap(conn, stintid);
int telemid = addtelemetry(conn, track_samples, stintlapid); int telemid = addtelemetry(conn, track_samples, stintlapid);
int b = updatetelemetry(conn, telemid, track_samples*sizeof(double), "steer", steerdata); int b = updatetelemetry(conn, telemid, track_samples*sizeof(double), "steer", steerdata);
b = updatetelemetry(conn, telemid, track_samples*sizeof(double), "accel", acceldata); b = updatetelemetry(conn, telemid, track_samples*sizeof(double), "accel", acceldata);
b = updatetelemetry(conn, telemid, track_samples*sizeof(double), "brake", brakedata); b = updatetelemetry(conn, telemid, track_samples*sizeof(double), "brake", brakedata);
//print_bytes(acceldata, tick*sizeof(double)); b = updatetelemetry(conn, telemid, track_samples*sizeof(int), "rpms", rpmdata);
print_bytes(&acceldata[pos], sizeof(double)); b = updatetelemetry(conn, telemid, track_samples*sizeof(int), "gear", geardata);
slogt("last accel %f on tick %i", acceldata[track_samples], track_samples); b = updatetelemetry(conn, telemid, track_samples*sizeof(int), "speed", speeddata);
slogt("telemetry respone: %i", b);
// close last stint lap and telemetry lap
tick = 0; tick = 0;
} }
lastpitstatus = pitstatus; lastpitstatus = pitstatus;

View File

@ -0,0 +1,130 @@
#ifndef _SESSION_H
#define _SESSION_H
#include <stddef.h>
#include <stdbool.h>
typedef struct DBData DBData;
typedef struct DBField DBField;
typedef struct SessionFieldsData SessionFieldsData;
typedef struct SessionFields SessionFields;
typedef struct Session Session;
typedef unsigned char PDBTimeStamp[26];
struct DBField
{
size_t offset;
size_t size;
int colnum;
int type;
char name[20];
};
//struct SessionFields
//{
// DBField session_id;
// DBField laps;
//};
typedef struct SessionRowData
{
int session_id;
int event_id;
int event_type;
//char track_time[5];
//char session_name[50];
//char start_time[6];
//int duration_min;
//int elapsed_ms;
int laps;
//char weather[100];
//double air_temp;
//double road_temp;
//double start_grip;
//double current_grip;
//int is_finished;
//char finish_time[6];
//char last_activity[6];
//int http_port;
}
SessionRowData;
//struct SessionFieldsData
//{
// int session_id;
// int laps;
//};
typedef struct StintRowData
{
int stint_id;
int driver_id;
int team_member_id;
int session_id;
int car_id;
int game_car_id;
int laps;
int valid_laps;
int best_lap_id;
}
StintRowData;
typedef struct LapRowData
{
int lap_id;
int stint_id;
int sector_1;
int sector_2;
int sector_3;
double grip;
unsigned char tyre[10];
int time;
int cuts;
int crashes;
int max_speed;
int avg_speed;
double f_tyre_temp;
double r_tyre_temp;
double f_tyre_wear;
double r_tyre_wear;
double f_tyre_press;
double r_tyre_press;
double f_brake_temp;
double r_brake_temp;
PDBTimeStamp finished_at;
}
LapRowData;
typedef struct SessionDbo
{
int numrows;
bool hasdata;
DBField fields[4];
SessionRowData* rows;
}
SessionDbo;
typedef struct StintDbo
{
int numrows;
bool hasdata;
DBField fields[9];
StintRowData* rows;
}
StintDbo;
typedef struct LapDbo
{
int numrows;
bool hasdata;
DBField fields[21];
LapRowData* rows;
}
LapDbo;
#endif

View File

@ -40,34 +40,47 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
// setup argument handling structures // setup argument handling structures
const char* progname = "Gilles"; const char* progname = "Gilles";
struct arg_lit* arg_verbosity = arg_litn("v","verbose", 0, 2, "increase logging verbosity"); struct arg_lit* arg_verbosity0 = arg_litn("v","verbose", 0, 2, "increase logging verbosity");
struct arg_lit* arg_verbosity1 = arg_litn("v","verbose", 0, 2, "increase logging verbosity");
struct arg_rex* cmd1 = arg_rex1(NULL, NULL, "play", NULL, REG_ICASE, NULL); struct arg_rex* cmd1 = arg_rex1(NULL, NULL, "play", NULL, REG_ICASE, NULL);
struct arg_rex* cmd2 = arg_rex1(NULL, NULL, "browse", NULL, REG_ICASE, NULL);
struct arg_str* arg_sim = arg_strn("s", "sim", "<gamename>", 0, 1, NULL); struct arg_str* arg_sim = arg_strn("s", "sim", "<gamename>", 0, 1, NULL);
struct arg_lit* arg_cli = arg_lit0("c", "textui", "text only ui"); struct arg_lit* arg_cli = arg_lit0("c", "textui", "text only ui");
struct arg_lit* arg_mqtt = arg_lit0("Q", "mqtt", "send data to local mqtt server with connection settings speciifed in config"); struct arg_lit* arg_mqtt = arg_lit0("Q", "mqtt", "send data to local mqtt server with connection settings speciifed in config");
struct arg_lit* arg_mysql = arg_lit0("M", "mysql", "send data to local mysql server with connection settings specified in config"); struct arg_lit* arg_mysql = arg_lit0("M", "mysql", "send data to local mysql server with connection settings specified in config");
struct arg_lit* help = arg_litn(NULL,"help", 0, 1, "print this help and exit"); struct arg_lit* help0 = arg_litn(NULL,"help", 0, 1, "print this help and exit");
struct arg_lit* vers = arg_litn(NULL,"version", 0, 1, "print version information and exit"); struct arg_lit* vers0 = arg_litn(NULL,"version", 0, 1, "print version information and exit");
struct arg_end* end = arg_end(20); struct arg_end* end0 = arg_end(20);
void* argtable[] = {cmd1,arg_sim,arg_verbosity,arg_cli,arg_mqtt,arg_mysql,help,vers,end}; struct arg_lit* help1 = arg_litn(NULL,"help", 0, 1, "print this help and exit");
int nerrors; struct arg_lit* vers1 = arg_litn(NULL,"version", 0, 1, "print version information and exit");
struct arg_end* end1 = arg_end(20);
void* argtable0[] = {cmd1,arg_sim,arg_verbosity0,arg_cli,arg_mqtt,arg_mysql,help0,vers0,end0};
void* argtable1[] = {cmd2,arg_verbosity1,help1,vers1,end1};
int nerrors0;
int nerrors1;
if (arg_nullcheck(argtable) != 0) if (arg_nullcheck(argtable0) != 0)
{
printf("%s: insufficient memory\n",progname);
goto cleanup;
}
if (arg_nullcheck(argtable1) != 0)
{ {
printf("%s: insufficient memory\n",progname); printf("%s: insufficient memory\n",progname);
goto cleanup; goto cleanup;
} }
nerrors = arg_parse(argc,argv,argtable); nerrors0 = arg_parse(argc,argv,argtable0);
nerrors1 = arg_parse(argc,argv,argtable1);
if (nerrors==0) if (nerrors0==0)
{ {
p->program_action = A_PLAY; p->program_action = A_PLAY;
p->sim_string = strdup(arg_sim->sval[0]); p->sim_string = strdup(arg_sim->sval[0]);
p->verbosity_count = arg_verbosity->count; p->verbosity_count = arg_verbosity0->count;
if (arg_cli->count > 0) if (arg_cli->count > 0)
{ {
p->cli = true; p->cli = true;
@ -83,17 +96,26 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
exitcode = E_SUCCESS_AND_DO; exitcode = E_SUCCESS_AND_DO;
} }
if (nerrors1==0)
{
p->program_action = A_BROWSE;
//p->sim_string = strdup(arg_sim->sval[0]);
p->verbosity_count = arg_verbosity1->count;
exitcode = E_SUCCESS_AND_DO;
}
// interpret some special cases before we go through trouble of reading the config file // interpret some special cases before we go through trouble of reading the config file
if (help->count > 0) if (help0->count > 0)
{ {
printf("Usage: %s\n", progname); printf("Usage: %s\n", progname);
arg_print_syntax(stdout,argtable,"\n"); arg_print_syntax(stdout,argtable0,"\n");
arg_print_syntax(stdout,argtable1,"\n");
printf("\nReport bugs on the github github.com/spacefreak18/gilles.\n"); printf("\nReport bugs on the github github.com/spacefreak18/gilles.\n");
exitcode = E_SUCCESS_AND_EXIT; exitcode = E_SUCCESS_AND_EXIT;
goto cleanup; goto cleanup;
} }
if (vers->count > 0) if (vers0->count > 0)
{ {
printf("%s Simulator Monitor\n",progname); printf("%s Simulator Monitor\n",progname);
printf("October 2022, Paul Dino Jones\n"); printf("October 2022, Paul Dino Jones\n");
@ -102,7 +124,8 @@ ConfigError getParameters(int argc, char** argv, Parameters* p)
} }
cleanup: cleanup:
arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0])); arg_freetable(argtable0,sizeof(argtable0)/sizeof(argtable0[0]));
arg_freetable(argtable1,sizeof(argtable1)/sizeof(argtable1[0]));
return exitcode; return exitcode;
} }

View File

@ -33,6 +33,7 @@ Parameters;
typedef enum typedef enum
{ {
A_PLAY = 0, A_PLAY = 0,
A_BROWSE = 0
} }
ProgramAction; ProgramAction;